Upmind MCP Server v3
Model Context Protocol server for the Upmind platform: bundled API documentation search plus 97 live admin tools covering the daily operations of a hosting business — tickets, billing, services, clients, orders, provisioning, promotions, security, and reporting.
Built for and verified against a production Upmind organisation.
Highlights
- 97 tools across 15 toolsets (read-only / write / destructive all annotated)
- Secure auth CLI — session tokens stored in the macOS Keychain, never plaintext;
upmind-mcp token setimports a fresh token straight from your clipboard - Read-only mode (
UPMIND_READ_ONLY=true) blocks every write tool - Token-efficient responses — list tools return compact summaries (pass
full: truefor raw records) - Resilient API client — retry with backoff on 429/5xx, timeouts, Upmind field-error extraction, 401 renew-and-replay
- Refreshable docs —
npm run update-docspulls the latest reference from apidocs.upmind.com (1,270+ endpoints incl. the web hosting module)
Install
Without cloning (recommended)
claude mcp add --transport stdio --scope user upmind -- npx -y github:spidyhost-crm/upmind-mcp-server
npx fetches and builds the server automatically; your config and tokens live in ~/.upmind-mcp/ + the Keychain, so updates never touch them.
From a clone
git clone git@github.com:spidyhost-crm/upmind-mcp-server.git && cd upmind-mcp-server
npm install && npm run build
claude mcp add --transport stdio --scope user upmind -- node $(pwd)/dist/index.js
Authentication
Your admin token controls the whole business — treat it accordingly. Two modes:
Browser temp-token mode (recommended — maximum control)
Nothing long-lived is ever stored. Session tokens expire after ~1 hour.
- Log into your Upmind admin as usual
- DevTools → Network → any
api.upmind.iorequest → copy the Bearer token npx upmind-mcp token set— reads the clipboard, validates against the live API, stores in the macOS Keychain
When it expires, tools return a clear error telling you to repeat step 2–3.
Auto-renewal mode (convenience)
upmind-mcp login (email + password + 2FA) stores a session and refresh token in the Keychain; the server renews access tokens itself and rotates the stored pair. Revoke anytime by logging that session out in Upmind or upmind-mcp token clear.
CLI reference
upmind-mcp token set|show|clear manage the stored token (Keychain-backed)
upmind-mcp login full login with auto-renewal
upmind-mcp whoami verify credentials against the live API
upmind-mcp status show config, backend, token expiry
Security model
- Keychain storage (macOS): tokens encrypted at rest by the OS;
UPMIND_TOKEN_BACKEND=filefalls back to~/.upmind-mcp/tokens.jsonchmod 600 - Least privilege: create a dedicated staff/API user in Upmind with a restricted role for this server instead of using an owner account
- IP whitelisting: use the built-in
list/add/remove_whitelisted_iptools to restrict org admin access to known IPs — a leaked token becomes useless elsewhere. Add your current IP first! - Read-only mode:
UPMIND_READ_ONLY=truehard-blocks all 48 write tools server-side - Destructive-tool annotations: cancels/refunds/deletes carry
destructiveHintso MCP clients can require confirmation - Never paste tokens into chats or commit them —
.env,.tokens.jsonare gitignored; the CLI clipboard flow avoids both
Configuration
Config is layered: real env vars → project .env → ~/.upmind-mcp/config.env.
| Env | Effect | |---|---| | UPMIND_ORIGIN | Your admin URL (e.g. https://secure.spidyhost.com) — required for OAuth flows | | UPMIND_API_BASE | Default https://api.upmind.io/api/admin | | UPMIND_READ_ONLY=true | Every write tool refuses to run | | UPMIND_DEFAULT_BRAND_ID | Applied when tools accept brand_id and none is given | | UPMIND_TOOLSETS=tickets,billing | Expose only selected toolsets (docs always on) | | UPMIND_TOKEN_BACKEND | keychain / file (default auto) | | UPMIND_API_TOKEN / UPMIND_REFRESH_TOKEN / UPMIND_USERNAME+UPMIND_PASSWORD | Env-based auth alternatives to the CLI | | UPMIND_TIMEOUT_MS / UPMIND_MAX_RETRIES / UPMIND_DEBUG | Client tuning |
Tool catalog
docs — search_endpoints, get_endpoint_details, list_api_groups, get_group_endpoints
brands — list_brands, get_brand
catalog — list_categories, create_category, list_products, get_product, create_product, update_product, duplicate_product, copy_product_to_brand, reorder_products, list_pricelists, get_product_prices, sync_pricing, list_currencies, get_upgrade_paths, set_upgrade_paths, remove_upgrade_path
provisioning — list_provision_fields, get_provision_field_values, update_provision_field_values, list_provision_configs, list_provision_functions
contracts (services) — list_contracts, get_contract, count_active_services, cancel_contract, cancel_contract_product, activate_contract_product, set_contract_product_renewal, update_contract_product_dates, update_contract_product_price, change_contract_product (upgrades, with dry_run), trigger_provision
clients — list_clients, get_client, create_client, update_client, list_client_accounts, reset_client_password, resend_client_verification
orders — list_orders, get_order, create_order (quick order → invoice), cancel_order, convert_order_to_invoice
billing — list_invoices, get_invoice, credit_invoice, apply_client_credit, refund_invoice, create_renewal_invoice, refresh_invoice, list_payments, add_payment, refund_payment, list_gateways, get_wallet_balance, list_wallet_transactions, refund_from_wallet
tickets — list_tickets, get_ticket, get_ticket_messages, create_ticket, reply_ticket (incl. private staff notes), update_ticket, assign_ticket, list_ticket_departments
marketing — list_promotions, get_promotion, create_promotion, update_promotion, disable_promotion, list_leads, create_lead, update_lead, convert_lead_to_client
emails — list_email_history, get_email, resend_email
webhooks — list_webhooks, list_webhook_events, create_webhook, update_webhook, delete_webhook
users — list_users, get_user
reports — get_stats, list_reports, run_report
security — list_whitelisted_ips, add_whitelisted_ip, remove_whitelisted_ip
Upmind API knowledge baked in
Verified against production:
- Admin prefix: staff tokens call
https://api.upmind.io/api/admin/...; doc URLs startingadmin/map to the same path with the prefix stripped. - Pagination: Upmind returns 10 results by default — always pass
limit/offset; responses carrytotal. The client'sgetAll()auto-paginates (capped at 1,000 items). - Filters:
filter[field]=value, e.g.filter[status.code],filter[product.id],filter[contract.client_id]. ⚠️filter[status]=...on invoices causes a 500 database error — always filter status viastatus.code. - Status codes are prefixed:
contract_active,contract_suspended,invoice_unpaid,invoice_paid,ticket_in_progress,ticket_waiting_response(short forms likeunpaidalso match). - Relations load via
with=a,b,c; raw list rows only carry*_idfields (e.g. tickets havestatus_idbut no status object withoutwith=status). - OAuth:
POST https://api.upmind.io/oauth/access_tokenwithadmin_password/admin_twofa/refresh_tokengrants; theOriginheader of your admin domain is required when no oauth client id is sent. Access tokens live ~1 hour; refresh tokens rotate on every use. - Emails: the API exposes delivery metadata (
sent,bounced,error_message) but not rendered bodies.
Architecture
src/
├── index.ts # stdio server entry (existing MCP registrations)
├── cli.ts # upmind-mcp CLI: token/login/whoami/status + serve
├── serve.ts # shared server bootstrap
├── server.ts # assembles McpServer from the tool registry
├── registry.ts # ToolDef type + shared schema fragments
├── config.ts # layered env/.env/~/.upmind-mcp config
├── api/
│ ├── client.ts # HTTP client: retries, timeouts, error shaping
│ ├── auth.ts # TokenManager: OAuth renewal, expiry handling
│ └── token-store.ts # Keychain (macOS) / file token storage
├── docs/ # documentation cache, search, and doc tools
├── tools/ # one file per domain, exporting ToolDef[]
└── utils/compact.ts # response summarisation helpers
scripts/
├── update-docs.mjs # refresh bundled docs (npm run update-docs)
└── smoke.mjs # read-only live smoke test (npm run smoke)
data/ # bundled apidoc JSON (refreshable)
Adding a tool = adding one entry to a domain file. server.ts handles registration, read-only enforcement, annotations, and error shaping centrally.
Development
npm run build # compile
npm run typecheck # type check only
npm run smoke # read-only smoke test against the live API
npm run update-docs # refresh bundled API docs
License
MIT











