Docs

MCP setup guide

Connect any Model Context Protocol client to your Vectis tenant. Vectis ships no AI model — your client of choice (or none) calls Vectis on your behalf.

What is the Vectis MCP server?

Vectis ships no AI model. This endpoint lets your MCP-compliant client read your Vectis data on your behalf, with the same permissions you have in the UI. The protocol it speaks is the open-standard Model Context Protocol.

Per-tenant isolation

  • Each Vectis tenant has its own database and subdomain. Tokens are sha256-hashed and live only in the tenant DB that issued them.
  • A token issued at acme.mspvectis.com cannot authenticate at northwind.mspvectis.com — the hash literally does not exist in the other tenant’s database.
  • MCP tools never accept a tenant_id parameter. The tenant is implicit in the URL + token; there is no documented call shape that can return another tenant’s data.

1. Generate a token

From the operator UI, open /account/mcp, click Generate token, pick a label and scopes, and copy the raw value. It is shown exactly once.

2. Connect Claude Desktop

Paste the snippet from the issuance dialog into your claude_desktop_config.json file (per Anthropic’s Claude Desktop user quickstart). The snippet uses mcp-remote to bridge Claude Desktop’s stdio transport to the Vectis HTTP endpoint.

{
  "mcpServers": {
    "vectis": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://{your-tenant}.mspvectis.com/api/mcp",
        "--header",
        "Authorization:${VECTIS_TOKEN}"
      ],
      "env": {
        "VECTIS_TOKEN": "Bearer vct_pat_••••••••••••••••"
      }
    }
  }
}

Restart Claude Desktop after editing the config; the Vectis tools should appear in the tool picker.

3. Connect Claude.ai (web) via Connectors

Vectis exposes an OAuth 2.1 authorization server at the tenant subdomain, so Claude.ai web Connectors and ChatGPT custom connectors can authorize via the standard PKCE flow. You do not need a Vectis PAT for these surfaces.

  1. Open Claude.ai → Settings → Connectors → Add.
  2. Paste your tenant’s MCP URL: https://{your-tenant}.mspvectis.com/api/mcp.
  3. Click Connect.
  4. Claude.ai will redirect you to your Vectis login. Sign in (and complete MFA if enabled), review the requested scopes on the Vectis consent screen, then click Authorize.
  5. Claude.ai stores the issued access + refresh token and the connector is ready. Vectis tools appear in the Claude.ai tool picker.

Per the MCP authorization spec, the flow is OAuth 2.1 + PKCE (S256) + RFC 8707 resource indicators. Vectis discovers Claude.ai’s client metadata via the Client ID Metadata Document the client hosts; no pre-registration is required.

4. Connect ChatGPT (custom GPT custom connectors)

ChatGPT’s custom connector UI accepts an MCP URL and completes the same OAuth 2.1 flow as Claude.ai. Paste https://{your-tenant}.mspvectis.com/api/mcp into the connector configuration; ChatGPT will redirect you to Vectis to sign in and approve scopes, then store the issued tokens.

For automations that need a long-lived static bearer (e.g. the Claude API MCP connector or an in-house script), keep using a PAT issued from /account/mcp — the two paths coexist permanently.

OAuth discovery + endpoints

OAuth-aware MCP clients discover the authorization server by fetching the RFC 9728 Protected Resource Metadata document at https://{your-tenant}.mspvectis.com/.well-known/oauth-protected-resource. The RFC 8414 authorization-server metadata lives at https://{your-tenant}.mspvectis.com/.well-known/oauth-authorization-server and advertises PKCE S256 support, dynamic client registration, and Client ID Metadata Document support. Clients that prefer to pre-register can POST to https://{your-tenant}.mspvectis.com/oauth/register per RFC 7591.

Every issued access token is bound to this tenant’s canonical resource URI via RFC 8707 resource indicators. A token issued at acme.mspvectis.com is rejected at northwind.mspvectis.com’s /api/mcp endpoint even if both clients somehow shared registration state. This is the same cross-tenant guarantee as PATs, enforced at the OAuth layer.

5. Connect Cursor

Per Cursor’s MCP docs, add this to ~/.cursor/mcp.json (global) or.cursor/mcp.json (per-project):

{
  "mcpServers": {
    "vectis": {
      "url": "https://{your-tenant}.mspvectis.com/api/mcp",
      "headers": {
        "Authorization": "Bearer vct_pat_••••"
      }
    }
  }
}

Cursor speaks HTTP natively; no mcp-remote wrapper is required.

6. Connect a self-hosted client (Ollama + Continue / LibreChat / open-webui)

MSPs whose policy forbids third-party AI processors can run a local model and point it at Vectis with the same bearer token. The local model never sends Vectis data to any vendor — the request stays on the operator’s machine. See your client’s MCP configuration docs for the bearer-header syntax.

Tool catalog — read

Required scopes are listed in brackets. Inputs and responses are documented in each tool’s JSON Schema, returned by the MCP tools/list call.

  • list_customersList customers in this tenant, optionally filtered by name (substring) or status. Returns id, name, city/state, status, MRR, and health snapshot. [read:customers]
  • get_customerGet full context for a single customer: address, primary contact, MRR/ARR, health score, plus rollups (open ticket count, open alert count, connected sources). [read:customers]
  • list_open_ticketsList open tickets across all sources (PSA + portal). Defaults to all open tickets across all customers when no filter is given. [read:tickets]
  • get_ticketGet a single ticket with its conversation thread (newest 25), priority/status, requester, assignee, and linked customer. [read:tickets]
  • search_ticketsFull-text search across ticket subject + ticket number + requester email. Uses trigram similarity from the Phase 153B index. [read:tickets, read:search]
  • list_alertsList RMM alerts, optionally filtered by customer / severity / status. Defaults to all open alerts when no filter is given. [read:alerts]
  • get_alertGet a single alert with linked device, acknowledgment / resolution history, and correlated incident id. [read:alerts]
  • list_assetsList assets (devices) for a customer or across the tenant. Optional filters: customer_id, kind (server/workstation/…), status. [read:assets]
  • get_assetGet a single asset (device) with full hardware / OS / warranty / lifecycle metadata, plus linked customer + site. [read:assets]
  • list_contractsList managed-services contracts. Optional filters: customer_id, expiring_within_days (defaults to all active contracts when omitted). [read:contracts]
  • list_backups_failingList failed (or warning-state) backup jobs across all backup vendors. Defaults to the last 7 days; widen with the `since` filter. [read:assets]
  • list_invoicesList billing invoices, optionally filtered by customer_id, status (open/paid/overdue/…), or since (only invoices issued at or after this ISO date). [read:billing]
  • list_recent_changesRecent operator-authored notes for a customer (or across all customers). Provides the unified-timeline starting point. [read:notes]
  • search_globalGlobal search across customers, tickets, devices, alerts, and notes. Returns the top hits per category, ranked by trigram similarity. [read:search]
  • list_rulesList rules-engine rule definitions. Read-only — does not run a rule. Filter by enabled state. [read:search]
  • list_rule_executionsList rules-engine execution history including the dead-letter queue. Filter by rule_id, status, or since-timestamp. [read:search]
  • get_customer_status_snapshotHigh-density 'everything for this account' snapshot. Returns identifying fields, MRR, open ticket counts + top 5, open alert counts + top 5, failing backups in last 7d, contracts expiring within 60 days, and per-source last sync times. Designed as the AI's grounding call. [read:customers, read:tickets, read:alerts]
  • list_my_assignmentsTickets assigned to the user who issued this MCP token (matched by email). Includes only open statuses. [read:tickets]
  • get_audit_log_for_ticketReturn audit-log rows whose target references the given ticket id (or its uuid prefix). Operators can verify which actor / system performed a write-back. [read:tickets]

Tool catalog — write

Write tools mutate vendor state and are gated by:

  • Scope — at least one of write:tickets, write:alerts, write:notes, run:rules must be granted on the token.
  • Idempotency-key — pass idempotency_key (any string up to 200 chars) alongside the tool arguments. Retried calls with the same key within 24h replay the original response — no duplicate tickets, no reply storms.
  • Dry-run — pass dry_run: true to preview the call without dispatching to the vendor. The response shows the resolved PSA / customer / payload; the audit row records mcpToolCallStatus="dry_run".
  • Per-token rate limit — 60 writes / hour with a 10 writes / minute burst. Exceeded calls return MCP error -32002 with data.retryAfterSeconds.
  • MFA elevation — tools marked "MFA" below additionally require the calling token to have been elevated in the last 24h. Elevate from /account/mcp. Otherwise the tool returns MCP error -32003 with a deep-link to the elevation page.
  • Per-tenant capability gating — write tools whose underlying connector is not enabled on this tenant are absent from tools/list entirely. See the matrix below.
  • create_ticketCreate a ticket in the customer's primary PSA (ConnectWise, Autotask, HaloPSA, or Atera — whichever the tenant has connected). Same dispatch the customer-hub New ticket dialog uses. Supports dry-run preview and idempotency_key. [write:tickets]
  • reply_to_ticketPost a customer-visible reply (note) to an existing PSA ticket. Wraps BaseConnector.addNote with isPrivate=false. Supports dry-run and idempotency_key. [write:notes]
  • add_internal_notePost a staff-only internal note to an existing PSA ticket. Wraps BaseConnector.addNote with isPrivate=true. Customers do not see internal notes. [write:notes]
  • close_ticketMove an existing PSA ticket to the canonical 'closed' status. Wraps BaseConnector.updateTicket with status='closed' and the optional resolution_summary as the closing note. High-trust: requires MFA-elevation on the token. [write:tickets] MFA
  • acknowledge_alertAcknowledge a NinjaOne RMM alert. Wraps POST /v2/alert/{id}/reset on the vendor side. Only NinjaOne alerts can be acknowledged via MCP — Atera/Datto/Kaseya/N-central don't expose vendor APIs for this verb (per Phase 137/141/142 audit). Supports dry-run. [write:alerts]
  • resolve_alertResolve a NinjaOne RMM alert. Wraps DELETE /v2/alert/{id} on the vendor side. Only NinjaOne alerts can be resolved via MCP — Atera/Datto/Kaseya/N-central don't expose vendor APIs for this verb (per Phase 137/141/142 audit). Supports dry-run. [write:alerts]
  • run_ruleManually fire a rules-engine rule. Enqueues rule_executions rows that the worker picks up via the same path as event-driven firings. Defaults to dry-run for safety. Optional simulated_event_id pins the trigger to a specific alert / ticket; omit it to fan out over a recent-events window. Requires run:rules scope + MFA-elevation on the token. [run:rules] MFA

Per-vendor capability matrix

MCP write tools share their parity surface with the rules- engine actions (per CLAUDE.md, the rules-engine action enum is the authoritative parity surface). What works for one works for the other.

VendorTools availableTools absent
ConnectWise Manage create_ticket, reply_to_ticket, add_internal_note, close_ticket
Autotask create_ticket, reply_to_ticket, add_internal_note, close_ticket
HaloPSA create_ticket, reply_to_ticket, add_internal_note, close_ticket
Atera create_ticket, reply_to_ticket, add_internal_note, close_ticketacknowledge_alert, resolve_alert — Atera’s alerts API has no documented update verb.
NinjaOne acknowledge_alert, resolve_alert
Datto BCDR acknowledge_alert, resolve_alert — Datto BCDR REST surface is read-only.
Kaseya VSA X acknowledge_alert, resolve_alert — Kaseya VSA X notifications API documents only DELETE (destructive); no acknowledge or close verb.
N-able N-central acknowledge_alert, resolve_alert — N-central exposes no documented notification-update REST verb.

Security and audit

  • Every tool call lands in the tenant audit log with the calling user, the token prefix, redacted arguments, and the result size.
  • Tokens can be revoked instantly from /account/mcp. Revocation takes effect on the next request — there is no cache.
  • Token expiry defaults to 90 days. The UI offers 30/90/365 days or “never”.
  • Does Vectis send my data to Anthropic / OpenAI? No. Vectis does not call any AI vendor. Your client calls Vectis. If your client is Claude or ChatGPT, then that vendor sees the data your client requested, under your contract with them, not ours. For zero third-party AI processing, use a self-hosted client (Ollama, LM Studio).

Troubleshooting

  • 401 Unauthorized — token missing, malformed, expired, or revoked. The response carries a WWW-Authenticate: Bearer … header that references /.well-known/oauth-protected-resource (per RFC 9728).
  • JSON-RPC error -32001 — token lacks a required scope. Re-issue with the scope added.
  • JSON-RPC error -32002 — per-token write rate limit exceeded (60/hour, burst 10/minute). Responsedata.retryAfterSeconds tells the client how long to back off.
  • JSON-RPC error -32003 — step-up MFA required. Open the link in data.elevationPath (/account/mcp) and elevate the token, then retry.
  • JSON-RPC error -32004 — unknown tool, OR the tool exists but is not available on this tenant (e.g. the tenant has no PSA connector enabled).
  • JSON-RPC error -32602 — invalid arguments for a tool. Check the tool’s inputSchema from tools/list.
  • JSON-RPC error -32601 — unknown JSON-RPC method. Only initialize, ping,tools/list, tools/call, and notifications/* are implemented.