SyncroMSP MCP Server
Gives AI assistants full access to SyncroMSP IT/MSP platform with 190 tools across 16 domains for managing tickets, customers, assets, invoices, and more.
Tickets: CRUD, comments (email/public/private), line items, timers, attachments, blueprints, cross-ticket comment feed.
Customers: CRUD, phone numbers, autocomplete, latest customers.
Assets: CRUD, patches, installed applications, policy folder assignment, custom properties.
Contacts: CRUD.
Invoices: CRUD, line items (manual/catalog), print, email, draft publish/convert.
Estimates: CRUD, line items, print, email, convert to invoice.
Appointments: CRUD, types, ticket linking.
Products: CRUD (no delete), serials, SKUs, categories, images, barcode lookup, location quantities.
Payments: Create, read, multi-invoice distribution, payment profiles/methods.
Other domains: Leads, contracts, RMM alerts/scripts, scheduling (recurring invoices), time tracking, admin (search, users, vendors, wiki, portal, settings, POs), policies.
Includes rate limiting (180 req/min), confirmation for destructive operations, and OAuth 2.1 for remote Docker deployments.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@SyncroMSP MCP Server show open tickets assigned to me"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
SyncroMSP MCP Server
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.
Features
190 tools across 16 domains, covering every current endpoint in Syncro's API docs
Full CRUD for tickets, customers, invoices, estimates, appointments, contracts, products, and more
Ticket comments — email replies, public notes, and private/internal notes
Line items — add products from catalog or manual entries to tickets, invoices, estimates, schedules
RMM — create, read, mute, resolve alerts on assets; run scripts on an asset now or once later
Rate limiting — built-in 180 req/min token bucket (Syncro API limit)
Confirmation required for all destructive operations (DELETE, etc.)
Auto-update check — warns on startup if a newer version is available
Deployment Options
Method | Best For | Auto-Updates |
One-command install of MCP + Skill in Claude Code | Yes (marketplace) | |
Developers wiring up the MCP without the bundled skill | Yes (npx) | |
Local desktop app users | Yes (npx) | |
Teams, remote access, Claude.ai web | Yes (Watchtower) | |
Development and customization | Manual |
Bundled Skill
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@syncromspOn 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.zipThe zip is rebuilt on every release. Skill-only changes committed as docs(skill): ... cut a patch release, so they reach the zip.
Related MCP server: Autotask MCP Server
Prerequisites
Getting Your Syncro API Key
Log in to your Syncro account
Go to Admin > API Tokens
Click + New Token
Select the Custom Permissions tab
Name your token and set permissions for the resources you need
Click Create and copy the token (it cannot be retrieved later)
Your subdomain is the part before .syncromsp.com in your Syncro URL (e.g., mycompany from mycompany.syncromsp.com).
Claude Code
claude mcp add syncromsp \
--env SYNCRO_API_KEY=your-api-key \
--env SYNCRO_SUBDOMAIN=your-subdomain \
-- npx syncromsp-mcpThat's it. Claude Code will download and run the latest version automatically.
Claude Desktop
Option 1: MCPB Extension
Download the latest .mcpb file from Releases and double-click to install. Claude Desktop will prompt you for your API key and subdomain.
Option 2: Manual Configuration
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:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
Restart Claude Desktop after saving. The server updates automatically via npx on each restart.
Docker Deployment (Remote MCP)
Deploy as a Docker container for remote access from Claude.ai, shared team usage, or running on a server. Each person signs in with their own Syncro API key, so every action in Syncro is made as that person, with that key's permissions. There is no shared password and no server-wide Syncro key.
Step 1: Clone and Configure
git clone https://github.com/advenimus/syncromsp-mcp.git
cd syncromsp-mcp
cp .env.example .envEdit .env with your settings:
# 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: 32 random bytes that encrypt every sign-in token.
# Generate with: openssl rand -hex 32
# Keep it secret and keep it stable: changing it signs everyone out.
MCP_TOKEN_ENCRYPTION_KEY=
# Required: which Syncro accounts may sign in. Set ONE of these three.
SYNCRO_SUBDOMAIN=yourcompany # lock sign-in to one account
# MCP_ALLOWED_SUBDOMAINS=acme,beta # or allow a list of accounts
# MCP_ALLOW_ANY_SUBDOMAIN=true # or allow any Syncro accountDo not set SYNCRO_API_KEY for this setup. It is ignored in HTTP sign-in mode.
Hosting for any Syncro account: set MCP_ALLOW_ANY_SUBDOMAIN=true and leave SYNCRO_SUBDOMAIN unset. The sign-in page then asks for both the subdomain and the API key, so any Syncro tenant can connect with its own credentials. Each tenant only ever reaches its own Syncro account, gets its own outbound rate budget inside a server-wide one, and each user is limited to MCP_MAX_SESSIONS_PER_USER open sessions.
Step 2: Deploy
docker compose up -dThe container runs on port 8080 by default. You need a reverse proxy (Traefik, Caddy, nginx) in front to provide HTTPS.
Step 3: Connect from Claude.ai
In Syncro, create an API token for yourself under Admin > API Tokens. Its permissions decide what Claude can do.
In Claude.ai, go to Settings > MCP Servers > Add Remote Server
Enter your MCP URL:
https://mcp.yourcompany.com/mcpClaude.ai will auto-discover the OAuth endpoints
A sign-in page appears. Enter your Syncro subdomain (unless the server is locked to one) and your API key.
The server checks the key with Syncro. If Syncro accepts it, Claude.ai connects and all tools become available.
Each teammate repeats steps 1 to 6 with their own key.
How Sign-in Works
The server implements the MCP OAuth 2.1 + PKCE spec. The login step is your own Syncro key:
Client connects → 401 Unauthorized
→ Client discovers /.well-known/oauth-authorization-server
→ Client dynamically registers (RFC 7591)
→ Client redirects user to /authorize
→ User enters Syncro subdomain + API key
→ Server calls https://<subdomain>.syncromsp.com/api/v1/me with that key (5 second timeout)
→ Syncro says OK: auth code issued → tokens granted → MCP access
→ Anything else: one generic "Sign-in failed" message, nothing issuedNo credential database. Your subdomain and key live only inside your tokens, which are encrypted and signed with AES-256-GCM using
MCP_TOKEN_ENCRYPTION_KEY. The server stores nothing on disk.Sign-ins survive restarts. Tokens and client registrations are self-contained encrypted blobs, so a restart or redeploy does not sign anyone out (as long as
MCP_TOKEN_ENCRYPTION_KEYstays the same).Each session uses its owner's key. A session is bound to the key that opened it. Another user presenting that session id gets a 404.
Access tokens last 1 hour. Refresh tokens last 30 days and are replaced on every use. Reusing an old refresh token cancels that whole sign-in.
The subdomain must be a plain name like
mycompany. The server always buildshttps://<subdomain>.syncromsp.comitself, so it cannot be pointed at another host.Failed sign-in attempts are limited to 5 per IP address per 15 minutes. Successful sign-ins do not count.
The key is never put in a URL, a log line, or an error message.
The sign-in page shows the
redirect_uriso users can check where they will be sent (anti-phishing).
Signing out and revoking access
To cut off a key for sure, delete it in Syncro (Admin > API Tokens). Every token that carries it stops working at Syncro right away. This is the real kill switch.
Claude.ai's "disconnect" calls the revoke endpoint. Revoked tokens are remembered in memory until they expire. That memory resets when the server restarts, so a restart re-enables a revoked token that has not expired yet. If that matters, delete the key in Syncro.
Rotating the encryption key
Generate a new key:
openssl rand -hex 32Move the current value to
MCP_TOKEN_ENCRYPTION_KEY_PREVIOUSand put the new one inMCP_TOKEN_ENCRYPTION_KEY. Restart.Existing sign-ins keep working. New and refreshed tokens use the new key.
After 30 days (the refresh token lifetime), remove
MCP_TOKEN_ENCRYPTION_KEY_PREVIOUSand restart. Client registrations are sealed with the key too, so a client that registered before the rotation (for example a Claude.ai connector) may then need to be removed and re-added.
If the key may have leaked, do not keep it as the previous key: just replace it. Everyone has to sign in again, and Claude.ai may need the connector removed and re-added. Also ask users to delete and re-create their Syncro API keys, because a leaked encryption key plus a captured token reveals the Syncro key inside.
For the full threat model, defense layers, and operator responsibilities, see SECURITY.md.
Example: Docker with Traefik
services:
syncro-mcp:
image: ghcr.io/advenimus/syncromsp-mcp:latest
container_name: syncromsp-mcp
restart: unless-stopped
environment:
- MCP_TRANSPORT=http
- MCP_PORT=8080
- MCP_BASE_URL=https://mcp.yourcompany.com
- MCP_TOKEN_ENCRYPTION_KEY=${MCP_TOKEN_ENCRYPTION_KEY}
- SYNCRO_SUBDOMAIN=${SYNCRO_SUBDOMAIN}
# 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"Example: Docker with Caddy
services:
syncro-mcp:
image: ghcr.io/advenimus/syncromsp-mcp:latest
container_name: syncromsp-mcp
restart: unless-stopped
environment:
- MCP_TRANSPORT=http
- MCP_BASE_URL=https://mcp.yourcompany.com
- MCP_TOKEN_ENCRYPTION_KEY=${MCP_TOKEN_ENCRYPTION_KEY}
- SYNCRO_SUBDOMAIN=${SYNCRO_SUBDOMAIN}
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
}Disabling Auth (Not Recommended)
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:
In this mode there is no sign-in page, and every session uses one server-wide SYNCRO_API_KEY. The default docker-compose.yml does not pass that variable in, so add these lines under environment: first:
- SYNCRO_API_KEY=${SYNCRO_API_KEY}
- MCP_I_UNDERSTAND_INSECURE=${MCP_I_UNDERSTAND_INSECURE}Then start it:
MCP_AUTH=false MCP_I_UNDERSTAND_INSECURE=true SYNCRO_API_KEY=your-key SYNCRO_SUBDOMAIN=yourcompany docker compose up -dWarning: 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.
Upgrading from the shared-password setup
Older versions used one shared password (MCP_AUTH_SECRET) and one server-wide SYNCRO_API_KEY. To upgrade:
Add
MCP_TOKEN_ENCRYPTION_KEY(openssl rand -hex 32).Keep
SYNCRO_SUBDOMAINto lock sign-in to your account, or setMCP_ALLOWED_SUBDOMAINS/MCP_ALLOW_ANY_SUBDOMAIN=true.Remove
MCP_AUTH_SECRETandSYNCRO_API_KEY. (If left in place they are ignored, with a warning in the log.)Restart. Everyone signs in once with their own Syncro API key. In Claude.ai you may need to remove and re-add the connector, because old client registrations were kept in memory and are gone.
Environment Variables
Variable | Required | Default | Description |
| stdio, or HTTP with | — | Your Syncro API token. Ignored (with a warning) in HTTP sign-in mode, where each user brings their own. |
| stdio, or HTTP with | — | Your Syncro subdomain. In HTTP sign-in mode, setting it locks sign-in to that one subdomain. |
| No |
|
|
| No |
| HTTP listen port |
| For Docker | — | Public HTTPS URL (e.g., |
| No |
|
|
| HTTP sign-in mode | — | 32 random bytes as 64 hex chars or base64. Encrypts every token and client registration. Generate with |
| No | — | The old key during a rotation. Used only to read existing tokens, never to create new ones. |
| One of these three in HTTP sign-in mode | — | Comma list of subdomains allowed to sign in, e.g. |
| One of these three in HTTP sign-in mode | — | Set to |
| If | — | Must be |
| No |
|
|
| No |
| HTTP sessions unused this long are closed (checked every 5 minutes). Clients reconnect automatically. |
| Recommended | — | Comma list of client return addresses allowed to register, e.g. |
| No | — | Extra host names the server answers to besides the |
| No |
| Syncro calls per minute from this whole server, on top of each tenant's own 180/min budget. Syncro documents its limit per IP, and all tenants share the server's IP. Raise it only if you know Syncro counts your tenants separately. |
| No |
| Open HTTP sessions one signed-in user may hold. Past it, that user's least recently used session idle for at least a minute is closed; if none qualifies, the new one gets a 429. |
Available 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, list by contact, 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, publish draft / convert to draft |
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 (incl. delete), categories, images |
payments | Payment records | Create, read, multi-invoice distribution |
leads | Leads/opportunities | Create, read, update |
contracts | Service contracts | CRUD |
rmm | RMM alerts and scripts | Create, read, mute, resolve alerts; run a script on an asset (confirmation required) |
scheduling | Recurring invoices | CRUD, schedule line items (incl. asset, contact, policy folder, vendor, and backup line types) |
time | Timers and time logs | Start, pause, resume, stop live ticket timers; set billable; list and edit time logs |
admin | Search, users, vendors, wiki, portal, settings, purchase orders, and more | Various, incl. PO update and file attachments |
policies | Policy folders (Syncro accounts only) | List, get, create, update, delete folders; assign assets via |
Staying Up to Date
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 (auto) | Add Watchtower for automatic daily updates |
MCPB | Download latest |
From Source |
|
Auto-Update with Watchtower
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.40Then 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.
Important Notes
Destructive operations (DELETE, remove line item, etc.) require explicit confirmation
Line items cannot be added inline during resource creation — always add them via separate API calls after creating the parent resource
Ticket comments have 3 modes: email reply (
do_not_email: false), public note (do_not_email: true, hidden: false), and private note (hidden: true)Some resources have no DELETE endpoint (vendors, leads, products, assets) — use
disabled: truevia update insteadRate limit: 180 requests per minute per IP (enforced by Syncro, managed by built-in rate limiter). In HTTP mode each Syncro tenant has its own 180/min budget, and all calls also share one server-wide budget (
MCP_SERVER_RATE_LIMIT_PER_MINUTE, default 180) because every tenant calls Syncro from the same IP.
From Source
git 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 startDevelopment
npm run dev # Run with tsx (hot reload)
npm run build # Compile TypeScript
npm test # Run tests
npm run lint # Lint sourceLicense
MIT
Available Tools
190 toolsadmin_add_po_attachmentA
Attach a file (vendor quote, invoice, packing slip) to a purchase order. Give exactly one source: file_url (a direct download link; works everywhere), file_path (a file on this computer; local installs only), or file_base64 (only for tiny files you create yourself, like a short CSV, because the whole file must be written out). Allowed: JPEG, PNG, GIF, PDF, CSV, XLS, XLSX. Max 10 MB and 10 files per PO; the extension must match the real file type.
Inputs: id (required), name, file_url, filename, +2 more.
admin_add_po_line_itemA
Add a line item to a purchase order. Note: the product must have maintain_stock=true or the API returns 422.
Inputs: id (required), quantity (required), product_id (required).
admin_caller_idB
Look up caller information by phone number
Inputs: phone_number (required).
admin_create_canned_responseB
Create a canned response
Inputs: title (required), body, subject, canned_response_category_id.
admin_create_portal_invitationC
Send a portal invitation to a user
Inputs: id (required).
admin_create_portal_userA
Create a customer portal user. Always provide contact_id to associate a person/name -- without it the portal user shows as an anonymous email.
Inputs: email (required), password, contact_id, customer_id, +2 more.
admin_create_purchase_orderC
Create a purchase order
Inputs: vendor_id (required), user_id, due_date, paid_date, +9 more.
admin_create_user_deviceB
Register a user device for push notifications
Inputs: model, device_name, device_uuid, screen_size, +2 more.
admin_create_vendorC
Create a new vendor. Note: there is no delete endpoint for vendors.
Inputs: name (required), zip, city, email, +8 more.
admin_create_wikiC
Create a wiki page
Inputs: name (required), body, slug, asset_id, +2 more.
admin_create_worksheetB
Create a worksheet result for a ticket. Note: worksheet_template_id is required and must reference an existing admin-configured template.
Inputs: ticket_id (required), title, worksheet_template_id.
admin_delete_canned_responseA
DELETE a canned response. The user MUST confirm.
Inputs: id (required), confirmed (required).
admin_delete_portal_userB
DELETE a portal user. The user MUST confirm.
Inputs: id (required), confirmed (required).
admin_delete_wikiA
DELETE a wiki page. The user MUST confirm.
Inputs: id (required), confirmed (required).
admin_delete_worksheetB
DELETE a worksheet result. The user MUST confirm.
Inputs: id (required), confirmed (required), ticket_id (required).
admin_get_canned_settingsC
Get canned response settings
Inputs: no named parameters.
admin_get_meA
Get the currently authenticated user's profile
Inputs: no named parameters.
admin_get_printingB
Get printing settings
Inputs: no named parameters.
admin_get_purchase_orderB
Get a purchase order by ID
Inputs: id (required).
admin_get_settingsB
Get system settings
Inputs: no named parameters.
admin_get_tabsA
Get settings tabs configuration
Inputs: no named parameters.
admin_get_ticket_formC
Get a ticket form by ID
Inputs: id (required).
admin_get_userC
Get a user by ID
Inputs: id (required).
admin_get_user_deviceB
Get a user device by ID
Inputs: id (required).
admin_get_vendorB
Get a vendor by ID
Inputs: id (required).
admin_get_wikiB
Get a wiki page by ID
Inputs: id (required).
admin_get_worksheetC
Get a worksheet result by ID
Inputs: id (required), ticket_id (required).
admin_list_canned_responsesC
List canned ticket responses
Inputs: no named parameters.
admin_list_itemsB
List items (global item catalog)
Inputs: no named parameters.
admin_list_line_itemsA
List line items across invoices/tickets
Inputs: no named parameters.
admin_list_portal_usersC
List customer portal users
Inputs: no named parameters.
admin_list_purchase_ordersC
List purchase orders
Inputs: page.
admin_list_ticket_formsC
List new ticket forms
Inputs: no named parameters.
admin_list_usersB
List all users/technicians
Inputs: no named parameters.
admin_list_vendorsC
List vendors
Inputs: no named parameters.
admin_list_wikiC
List wiki pages
Inputs: page.
admin_list_worksheetsC
List worksheet results for a ticket
Inputs: ticket_id (required).
admin_otp_loginB
Login with a one-time password code
Inputs: code (required).
admin_process_ticket_formC
Submit/process a new ticket form
Inputs: id (required), appointments, ticket_details, customer_details.
admin_receive_purchase_orderC
Receive a line item on a purchase order
Inputs: id (required), line_item_id (required).
admin_searchA
Global search across Syncro (tickets, customers, assets, invoices, etc.)
Inputs: query (required).
admin_update_canned_responseC
Update a canned response
Inputs: id (required), body, title, subject, +1 more.
admin_update_portal_userD
Update a portal user
Inputs: id (required), email, password, portal_group_id, +1 more.
admin_update_purchase_orderA
Update a purchase order. Only status, general_notes, shipping_cents, delivery_tracking, and vendor_id can be changed. Syncro rejects the 'Finished' status while any line item is still unreceived.
Inputs: id (required), status, vendor_id, general_notes, +2 more.
admin_update_user_deviceC
Update a user device
Inputs: id (required), registration_token_gcm.
admin_update_vendorC
Update a vendor
Inputs: id (required), zip, city, name, +9 more.
admin_update_wikiC
Update a wiki page
Inputs: id (required), body, name, slug, +3 more.
admin_update_worksheetD
Update a worksheet result
Inputs: id (required), ticket_id (required), title, public, +4 more.
appointments_createA
Create a new appointment. When possible, link to a ticket via ticket_id -- this auto-populates the description with ticket details and the location from the customer address.
Inputs: end_at, all_day, summary, user_id, +10 more.
appointments_create_typeB
Create a new appointment type. Note: location_type is REQUIRED (API returns 422 without it). Integer value where 0 = 'customer'.
Inputs: name (required), location_type, email_instructions, location_hard_code.
appointments_deleteA
DELETE an appointment. The user MUST confirm.
Inputs: id (required), confirmed (required).
appointments_delete_typeA
DELETE an appointment type. The user MUST confirm.
Inputs: id (required), confirmed (required).
appointments_getB
Get a single appointment by ID
Inputs: id (required).
appointments_get_typeB
Get an appointment type by ID
Inputs: id (required).
appointments_listC
List appointments with optional date range filter
Inputs: mine, page, date_to, date_from.
appointments_list_typesA
List appointment types
Inputs: no named parameters.
appointments_updateC
Update an existing appointment
Inputs: id (required), end_at, all_day, summary, +10 more.
appointments_update_typeC
Update an appointment type
Inputs: id (required), name, location_type, email_instructions, +1 more.
assets_chat_infoB
Get chat information for assets by IDs
Inputs: ids (required).
assets_createA
Create a new customer asset. Note: asset_type_name must match an existing type in the account. Custom properties on create are IGNORED -- set them via assets_update after creation.
Inputs: name (required), customer_id (required), properties, asset_serial, +2 more.
assets_getA
Get a single asset by ID with full details
Inputs: id (required).
assets_get_installed_applicationsA
Get the paginated list of software applications installed on an asset. Returns name, vendor, version, and installed_at (falls back to first-seen date when no explicit install date is recorded).
Inputs: id (required), page, per_page.
assets_get_patchesB
Get patch information for an asset (available OS/software patches)
Inputs: id (required).
assets_listB
List customer assets with optional filters. Returns paginated results.
Inputs: page, query, customer_id, snmp_enabled, +1 more.
assets_list_by_contactA
List the assets linked to one contact, sorted by name. 50 per page.
Inputs: contact_id (required), page.
assets_updateA
Update an existing asset. Use this to set asset properties (hdd, manufacturer, model, os, cpu_name, ram, last_boot) after creation, as properties on create are ignored. Pass policy_folder_id to move the asset to a same-customer policy folder (see policies_list_folders).
Inputs: id (required), name, properties, customer_id, +4 more.
contacts_createB
Create a new contact for a customer
Inputs: name (required), customer_id (required), zip, city, +7 more.
contacts_deleteA
DELETE a contact permanently. The user MUST confirm.
Inputs: id (required), confirmed (required).
contacts_getA
Get a single contact by ID
Inputs: id (required).
contacts_listC
List contacts with optional filters
Inputs: page, customer_id.
contacts_updateB
Update an existing contact
Inputs: id (required), zip, city, name, +9 more.
contracts_createA
Create a new contract. Note: there is no 'notes' field -- 'description' is the only text field. The activity/notes section in the UI is not API-accessible.
Inputs: name (required), customer_id (required), sla_id, status, +7 more.
contracts_deleteA
DELETE a contract (soft-delete -- GET returns null after deletion, not 404). The user MUST confirm.
Inputs: id (required), confirmed (required).
contracts_getA
Get a contract by ID
Inputs: id (required).
contracts_listD
List contracts
Inputs: page.
contracts_updateB
Update a contract. Note: there is no 'notes' field -- 'description' is the only text field. The activity/notes section in the UI is not API-accessible.
Inputs: id (required), name, sla_id, status, +8 more.
customers_autocompleteB
Autocomplete search for customers by name or business
Inputs: query (required).
customers_createA
Create a new customer. Note: phone and mobile fields auto-create entries in the phones sub-resource.
Inputs: zip, city, email, notes, +22 more.
customers_create_phoneB
Add a phone number to a customer
Inputs: number (required), customer_id (required), label, extension.
customers_deleteA
DELETE a customer permanently. The user MUST confirm before executing.
Inputs: id (required), confirmed (required).
customers_delete_phoneA
Delete a phone number from a customer. The user MUST confirm.
Inputs: id (required), confirmed (required), customer_id (required).
customers_getA
Get a single customer by ID with full details
Inputs: id (required).
customers_latestB
Get the most recently created customers
Inputs: no named parameters.
customers_listA
List customers with optional filters. Returns paginated results.
Inputs: id, page, sort, email, +5 more.
customers_list_phonesA
List phone numbers for a customer
Inputs: customer_id (required).
customers_updateB
Update an existing customer. Only provided fields will be changed.
Inputs: id (required), zip, city, email, +13 more.
customers_update_phoneC
Update a phone number for a customer
Inputs: id (required), customer_id (required), label, number, +1 more.
estimates_add_line_itemA
Add a line item to an estimate. When using product_id, only product_id + quantity are needed -- the API auto-fills name, cost, and price from the product catalog.
Inputs: id (required), cost, item, name, +8 more.
estimates_convert_to_invoiceB
Convert an estimate to an invoice
Inputs: id (required).
estimates_createA
Create a new estimate. Note: line_items array in the create body is IGNORED by the API -- add line items via estimates_add_line_item after creation.
Inputs: customer_id (required), date, name, note, +5 more.
estimates_deleteA
DELETE an estimate permanently. The user MUST confirm.
Inputs: id (required), confirmed (required).
estimates_delete_line_itemB
Delete a line item from an estimate. The user MUST confirm.
Inputs: id (required), confirmed (required), line_item_id (required).
estimates_emailC
Email an estimate to the customer
Inputs: id (required).
estimates_getB
Get a single estimate by ID
Inputs: id (required).
estimates_listB
List estimates with optional filters
Inputs: page, status, customer_id, created_after.
estimates_printB
Generate a printable PDF for an estimate
Inputs: id (required).
estimates_updateB
Update an existing estimate
Inputs: id (required), date, name, note, +5 more.
estimates_update_line_itemC
Update a line item on an estimate
Inputs: id (required), line_item_id (required), cost, item, +5 more.
invoices_add_line_itemA
Add a line item to an invoice. When using product_id, only product_id + quantity are needed -- the API auto-fills name, cost, and price from the product catalog.
Inputs: id (required), cost, item, name, +11 more.
invoices_convert_to_draftA
Turn a published invoice back into a draft so it can be edited before re-publishing. Needs draft invoices turned on for the account (404 otherwise). Syncro refuses (422) if a payment has been applied, the invoice was posted to an accounting provider, or it is a refund.
Inputs: id (required).
invoices_createA
Create a new invoice. Note: line_items in the create body are IGNORED by the API -- add line items via invoices_add_line_item after creation.
Inputs: customer_id (required), date, note, number, +7 more.
invoices_deleteA
DELETE an invoice permanently. The user MUST confirm.
Inputs: id (required), confirmed (required).
invoices_delete_line_itemB
Delete a line item from an invoice. The user MUST confirm.
Inputs: id (required), confirmed (required), line_item_id (required).
invoices_emailC
Email an invoice to the customer
Inputs: id (required).
invoices_getA
Get a single invoice by ID
Inputs: id (required).
invoices_get_ticketC
Get the ticket associated with an invoice
Inputs: id (required).
invoices_listB
List invoices with optional filters
Inputs: page, paid, unpaid, ticket_id, +1 more.
invoices_printB
Generate a printable PDF for an invoice
Inputs: id (required).
invoices_publishA
Publish a draft invoice so it becomes a normal invoice. Needs draft invoices turned on for the account (404 otherwise). Refunds cannot be drafts, so Syncro refuses to publish them.
Inputs: id (required).
invoices_updateB
Update an existing invoice
Inputs: id (required), date, note, number, +7 more.
invoices_update_line_itemB
Update a line item on an invoice
Inputs: id (required), line_item_id (required), cost, item, +5 more.
leads_createB
Create a new lead. Note: leads have no DELETE endpoint. To soft-delete, use leads_update with disabled=true.
Inputs: zip, city, email, phone, +22 more.
leads_getA
Get a lead by ID
Inputs: id (required).
leads_listC
List leads/opportunities
Inputs: page.
leads_updateC
Update an existing lead
Inputs: id (required), zip, city, email, +15 more.
payments_createC
Record a payment. Use apply_payments to distribute a payment across multiple invoices.
Inputs: customer_id (required), ref_num, invoice_id, address_zip, +8 more.
payments_create_profileB
Create a stored payment profile for a customer
Inputs: customer_id (required), last_four, expiration, payment_profile_id, +1 more.
payments_delete_profileA
Delete a payment profile. The user MUST confirm.
Inputs: id (required), confirmed (required), customer_id (required).
payments_getA
Get a single payment by ID
Inputs: id (required).
payments_get_profileC
Get a payment profile by ID
Inputs: id (required), customer_id (required).
payments_listC
List payments
Inputs: page.
payments_list_methodsA
List available payment methods
Inputs: no named parameters.
payments_list_profilesA
List stored payment profiles for a customer
Inputs: customer_id (required).
payments_update_profileC
Update a payment profile
Inputs: id (required), customer_id (required), last_four, expiration.
policies_create_folderA
Create a new policy folder under an existing parent folder. customer_id, name, and parent_id are all required -- folders cannot be created at the root level (the root folder is auto-created per customer). Use policies_list_folders first to find the root or desired parent folder ID.
Inputs: name (required), parent_id (required), customer_id (required).
policies_delete_folderA
DELETE a policy folder permanently. The folder must not have child folders (422 otherwise). This action cannot be undone -- the user MUST confirm before executing this.
Inputs: id (required), confirmed (required).
policies_get_folderA
Get a single policy folder by ID with full details.
Inputs: id (required).
policies_list_foldersA
List policy folders for a customer. customer_id is required. Returns paginated results with each folder's parent_id, partial_policy_id (policy attached at this folder), and effective_policy_id (inherited policy).
Inputs: customer_id (required), page, per_page.
policies_update_folderA
Update an existing policy folder. Use this to rename, re-parent, or attach/detach a partial policy. Set partial_policy_id to null to detach the policy at this folder; the effective_policy_id then inherits from the parent.
Inputs: id (required), name, parent_id, partial_policy_id.
products_add_imagesB
Add images to a product
Inputs: id (required), files (required).
products_attach_serial_to_line_itemC
Attach serial numbers to a line item
Inputs: product_id (required), line_item_id (required), product_serial_ids (required), record_type.
products_barcodeB
Look up a product by barcode/UPC
Inputs: barcode (required).
products_categoriesB
List product categories
Inputs: no named parameters.
products_createA
Create a new product. Note: products have no DELETE endpoint -- use products_update with disabled=true instead. Custom properties on create may be ignored -- set via products_update after creation.
Inputs: name (required), notes, taxable, disabled, +17 more.
products_create_serialB
Create a serial number for a product
Inputs: product_id (required), serial_number (required), condition, price_cost_cents, +1 more.
products_create_skuB
Create a SKU for a product
Inputs: value (required), product_id (required), vendor_id.
products_delete_imageC
Delete an image from a product. The user MUST confirm.
Inputs: id (required), confirmed (required).
products_delete_skuA
DELETE a product SKU. The user MUST confirm.
Inputs: id (required), confirmed (required), product_id (required).
products_getB
Get a product by ID
Inputs: id (required).
products_listC
List products/inventory items
Inputs: page.
products_list_serialsB
List serial numbers for a product
Inputs: product_id (required).
products_list_skusC
List SKUs for a product
Inputs: product_id (required).
products_updateC
Update a product
Inputs: id (required), name, notes, taxable, +13 more.
products_update_location_qtyC
Update product quantity at a location
Inputs: id (required), quantity (required), location_quantity_id (required).
products_update_serialC
Update a product serial
Inputs: id (required), product_id (required), notes, condition, +3 more.
products_update_skuC
Update a product SKU
Inputs: id (required), product_id (required), value, vendor_id.
rmm_create_alertA
Create an RMM alert. Note: formatted_output (not in swagger) populates the 'Details' field in the UI. description maps to the 'Type' field. Include properties with trigger and description keys to match real alert structure.
Inputs: status, asset_id, resolved, properties, +3 more.
rmm_delete_alertA
DELETE (soft-resolve) an RMM alert. Sets resolved=true -- the alert is still readable via GET after deletion. The user MUST confirm.
Inputs: id (required), confirmed (required).
rmm_get_alertA
Get an RMM alert by ID
Inputs: id (required).
rmm_list_alertsC
List RMM alerts
Inputs: page, status, created_after.
rmm_mute_alertB
Mute an RMM alert. Requires mute_for parameter.
Inputs: id (required), mute_for (required).
rmm_schedule_scriptA
Run an RMM script on one asset, now or once at a later time. Recurring schedules are not allowed through the API. No API lists scripts, so get script_id from the script's page in Syncro. This runs code on a customer machine: the user MUST confirm.
Inputs: asset_id (required), run_type (required), confirmed (required), script_id (required), +4 more.
scheduling_add_line_itemA
Add a line item to a recurring invoice schedule. Needs name or product_id. Pricing is in cents (retail_cents, cost_cents) or dollars (price_retail, price_cost). recurring_type_id picks the line type, e.g. 4 bills a customer's assets by type and 9 bills the assets in a policy folder; the type-specific fields only apply to their type.
Inputs: id (required), name, taxable, user_id, +28 more.
scheduling_createA
Create a recurring invoice schedule. Always create with paused=true to prevent auto-firing during setup. Note: invoice-side fields (invoice name, employee, template, billing terms, memo) are NOT settable via API.
Inputs: customer_id (required), name, paused, next_run, +5 more.
scheduling_deleteA
DELETE a schedule. The user MUST confirm.
Inputs: id (required), confirmed (required).
scheduling_getC
Get a schedule by ID
Inputs: id (required).
scheduling_listC
List recurring invoice schedules
Inputs: page.
scheduling_remove_line_itemB
Remove a line item from a schedule. The user MUST confirm.
Inputs: id (required), confirmed (required), line_item_id (required).
scheduling_updateC
Update a schedule
Inputs: id (required), name, paused, next_run, +5 more.
scheduling_update_line_itemB
Update a line item on a schedule. Takes the same fields as scheduling_add_line_item; only the fields you send change.
Inputs: id (required), line_item_id (required), name, taxable, +29 more.
tickets_add_line_itemA
Add a line item (product/service charge) to a ticket. Note: name and description are REQUIRED even when using product_id (unlike invoices/estimates which auto-fill from catalog).
Inputs: id (required), name, taxable, quantity, +5 more.
tickets_add_timerA
Add a timer entry to a ticket for time tracking. Note: start_at is REQUIRED (API returns 422 without it). duration_minutes auto-calculates end_time from start_at.
Inputs: id (required), notes, end_at, user_id, +3 more.
tickets_attach_fileA
Attach a file to a ticket via URL
Inputs: id (required), files (required).
tickets_blueprints_applyA
Create tickets from a Blueprint -- spawns the parent ticket and any child tickets defined by the blueprint, all assigned to the given customer. Returns { ticket_id, child_ticket_ids }.
Inputs: id (required), customer_id (required).
tickets_blueprints_listA
List Ticket Blueprints available for ticket creation (hidden ones are excluded). Returns id, name, role, and children_count for each blueprint.
Inputs: page, per_page.
tickets_charge_timerB
Charge a timer entry on a ticket (convert to billable line item)
Inputs: id (required), timer_entry_id (required).
tickets_commentA
Add a comment to a ticket. Three comment modes: (1) Email reply: hidden=false, do_not_email=false sends email to customer. (2) Public note: hidden=false, do_not_email=true is visible on portal/invoice but no email sent. (3) Private note: hidden=true, do_not_email=true is tech-only and invisible to customer. Note: subject is REQUIRED or the API returns 422.
Inputs: id (required), body (required), subject (required), tech, +3 more.
tickets_createA
Create a new ticket. Requires customer_id and subject at minimum. Note: line_items cannot be added inline during creation -- use tickets_add_line_item after the ticket is created.
Inputs: subject (required), customer_id (required), end_at, number, +14 more.
tickets_deleteA
DELETE a ticket permanently. This action cannot be undone. The user MUST confirm before executing this.
Inputs: id (required), confirmed (required).
tickets_delete_attachmentA
Delete an attachment from a ticket. The user MUST confirm.
Inputs: id (required), confirmed (required), attachment_id (required).
tickets_delete_timerA
Delete a timer entry from a ticket. The user MUST confirm.
Inputs: id (required), confirmed (required), timer_entry_id (required).
tickets_getB
Get a single ticket by ID with full details
Inputs: id (required).
tickets_get_commentsC
Get all comments on a ticket
Inputs: id (required).
tickets_listA
List tickets with optional filters. Returns paginated results.
Inputs: mine, page, query, number, +10 more.
tickets_list_commentsA
List ticket comments across multiple tickets as a flat paginated feed (distinct from tickets_get_comments which is scoped to one ticket). Sorted by ticket_id ASC, created_at DESC. Scope via ticket_search_id, ticket_id, customer_id, contact_id, user_id, status, mine, or date filters. comment_created_after/before filter at the comment level; the other date filters operate on the parent ticket.
Inputs: mine, page, status, user_id, +11 more.
tickets_printB
Generate a printable PDF for a ticket
Inputs: id (required).
tickets_remove_line_itemA
Remove a line item from a ticket. The user MUST confirm before executing this.
Inputs: id (required), confirmed (required), ticket_line_item_id (required).
tickets_settingsA
Get ticket system settings
Inputs: no named parameters.
tickets_updateB
Update an existing ticket. Only provided fields will be changed.
Inputs: id (required), end_at, number, sla_id, +14 more.
tickets_update_line_itemB
Update a line item on a ticket
Inputs: id (required), ticket_line_item_id (required), name, taxable, +6 more.
tickets_update_timerC
Update a timer entry on a ticket
Inputs: id (required), timer_entry_id (required), notes, user_id, +3 more.
time_create_timerA
Start a live timer on a ticket for the API token's technician (user_id cannot be set). If that technician already has a running or paused timer on the ticket, Syncro resumes and returns it instead of making a second one. Omit billable to use the account default. For logging past work, use tickets_add_timer instead.
Inputs: ticket_id (required), notes, billable, comment_id, +1 more.
time_get_last_timelogA
Get the most recent time log entry for the current user
Inputs: no named parameters.
time_list_timelogsC
List employee time logs (clock in/out records)
Inputs: page, user_id.
time_list_timersA
List ticket timers across tickets. Filter by ticket, technician, timer state, customer, or derived billing status. Use status 'running' or 'paused' to find a timer to pause or stop.
Inputs: page, status, user_id, ticket_id, +2 more.
time_pause_timerA
Pause a running timer. Syncro returns 422 if the timer is not running.
Inputs: id (required).
time_start_timerA
Start a timer that has never run, or resume a paused one. Syncro returns 422 if the timer is already running or stopped.
Inputs: id (required).
time_stop_timerA
Stop a running or paused timer. If the account has 'charge timers by default' turned on, this also adds the charge line item to the ticket; otherwise charge it afterwards with tickets_charge_timer (timer_entry_id = this timer's ID). Syncro returns 422 if the timer is already stopped.
Inputs: id (required).
time_update_timelogC
Update a time log entry (clock in/out, lunch, notes)
Inputs: in_at, lunch, out_at, in_note, +1 more.
time_update_timerA
Change whether a ticket timer is billable. To start, pause, or stop a timer use time_start_timer, time_pause_timer, or time_stop_timer; to change notes or duration use tickets_update_timer.
Inputs: id (required), billable (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 190 tools
Many tools have clearly distinct purposes (e.g., tickets_list vs customers_get), but significant overlaps exist between timer tools (tickets_add_timer vs time_create_timer, time_start_timer, time_stop_timer) and comment tools (tickets_get_comments vs tickets_list_comments), which could lead to misselection despite descriptive hints.
Tools mostly follow a consistent domain_prefix_action pattern (e.g., tickets_list, customers_get, invoices_create), but minor deviations like the 'time_' prefix for ticket timers and non-verb names (products_barcode, customers_latest) slightly break the otherwise predictable convention.
With 190 tools, the set is extremely bloated far beyond a well-scoped range. Even for a large platform like SyncroMSP, this volume creates significant noise and makes it difficult for an agent to discover and select the right tool.
The surface covers most major domains with CRUD and lifecycle operations, but notable gaps exist such as no assets_delete and no payments_update. Agents can often work around these (e.g., using disabled=true for soft-delete), so the gaps are minor.
Maintenance
Related MCP Connectors
Connect any AI assistant to Syncro: manage tickets, invoices, customers, assets, and more.
Connect AI agents to 580+ APIs with OAuth or API-key auth. Hosted gateway; API pricing varies.
Connect AI agents to 1000+ apps with managed authentication and tool-calling.
Zero-setup MCP gateway securely connecting AI to your tools with authentication and workflows
Related MCP Servers
- AlicenseCqualityCmaintenanceProvides AI assistants with direct access to Autotask PSA for MSP operations. Enables natural language interaction for ticket management, time logging, company lookups, project tracking, and billing review through 39 comprehensive tools.10091 npmApache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to directly query and manage Autotask PSA data through natural language, including ticket triage, time entry creation, company lookups, project management, billing review, and more.Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to interact with AutoTask PSA data, supporting natural language ticket queries, updates, notes, and bulk export.MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to work directly with ConnectWise Manage through natural conversation, providing 53 tools for tickets, time entry, companies, contacts, projects, agreements, invoices, opportunities, and more.Apache 2.0