MCP Docs
Request access
Model Context Protocol

Deterministic pricing your AI agents can trust

Quotix MCP is a pricing brain for chat and automation workflows. Your agent asks for a quote — Quotix returns a verified total from fixed rules. No model guesses the number.

Overview

Quotix MCP exposes a company's pricing engine as MCP tools. An AI agent (in CloseBot, n8n, Claude, a custom app…) collects the job details from the customer, then calls Quotix to turn those details into a priced quote.

Deterministic

Prices come from rules stored per business — line-item formulas, surcharge modifiers, and a tax rate. The same inputs always produce the same total. No LLM sits in the pricing path.

Multi-tenant

One server, many businesses. A request identifies the business by its platform account ID (e.g. a GoHighLevel sub-account), and Quotix loads that company's rules.

Schema-driven

Each service type publishes a JSON Schema of the fields it needs. Your agent can discover the questions to ask instead of hard-coding them.

Separate from the Quotix web builder

This is the chat/automation pricing service. It is intentionally independent of the Quotix website form builder — see the FAQ.

Chat agent CloseBot / custom MCP client n8n / Claude / SDK Quotix MCP /mcp  •  /v1/* Database tenants + rules Price JSON

How it works

1 — Identify the business

Every call carries platform + external_id. Quotix maps that pair to a tenant, then loads the pricing engine for the requested service_type.

lookup
(platform, external_id)  →  tenant  →  pricing engine (by service_type)

"gohighlevel" + "ghl_sub_ny_445"  →  Empire HVAC NY  →  "AC Replacement" engine

2 — Discover the required inputs

Call get_quote_schema to get the engine's input_schema (JSON Schema) and its required_fields. Your agent asks the customer for exactly those.

3 — Get the verified quote

Call calculate_quote with the complete inputs. Quotix validates against the schema, runs the deterministic calculation, and returns the total plus a full breakdown.

Same brain, two protocols. The MCP tools and the REST endpoints run the exact same lookup → validate → calculate pipeline. Use MCP for agent frameworks; use REST for everything else.

Connection details

SettingValue
MCP endpointhttps://mcp.quotix.ai/mcp
TransportStreamable HTTP
Auth headerAuthorization: Bearer <QUOTIX_API_KEY>
API keyIssued by Quotix during onboarding. It is not a Supabase or GoHighLevel key — it is a dedicated secret for this API. Treat it like a password.
Without a valid key401 Unauthorized
Health check (no auth)GET https://mcp.quotix.ai/health
Not yet public. The production host mcp.quotix.ai is being provisioned. During onboarding you may be given a staging URL — substitute it wherever this page shows https://mcp.quotix.ai.

Quickstart

Pick your client. All of them need the endpoint URL and the Authorization header above.

n8n (MCP Client node)

  1. Add an MCP Client (or Tool MCP) node.
  2. Server URL: https://mcp.quotix.ai/mcp
  3. Transport: HTTP Streamable (not legacy SSE)
  4. Add header Authorization: Bearer <QUOTIX_API_KEY> (store it as a credential)
  5. Select the tool: get_quote_schema or calculate_quote
Behind nginx? Disable proxy buffering for /mcp, raise read/send timeouts to 300s+, and pass the Authorization header through. Ask the Quotix team for the reference n8n workflow.

Claude Desktop / generic MCP client

Clients that speak HTTP transport can point straight at the endpoint:

json
{
  "mcpServers": {
    "quotix-pricing": {
      "url": "https://mcp.quotix.ai/mcp",
      "headers": {
        "Authorization": "Bearer <QUOTIX_API_KEY>"
      }
    }
  }
}
If your client only supports stdio MCP servers, bridge to the HTTP endpoint with mcp-remote:
{
  "mcpServers": {
    "quotix-pricing": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://mcp.quotix.ai/mcp",
               "--header", "Authorization: Bearer <QUOTIX_API_KEY>"]
    }
  }
}

Cursor / VS Code

Add the same block to .cursor/mcp.json (project) or your global MCP config.

Python (fastmcp Client)

python
from fastmcp import Client

async with Client("https://mcp.quotix.ai/mcp", auth="<QUOTIX_API_KEY>") as client:
    schema = await client.call_tool("get_quote_schema", {
        "platform": "gohighlevel",
        "external_id": "ghl_sub_ny_445",
        "service_type": "AC Replacement",
    })
    print(schema.structured_content["required_fields"])

curl (connectivity check)

The MCP endpoint speaks JSON-RPC over HTTP. A quick tools/list:

bash
curl -sS https://mcp.quotix.ai/mcp \
  -H "Authorization: Bearer $QUOTIX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Tools reference

get_quote_schema

Return the input schema and required fields for a tenant's service type. Call this first so your agent asks the customer the right questions.

ArgumentTypeExample
platformstringgohighlevel
external_idstringghl_sub_ny_445
service_typestringAC Replacement

Success (structured content)

json
{
  "engine_id": "b7c1e0a2-...",
  "engine_name": "Residential AC Replacement",
  "service_type": "AC Replacement",
  "tenant_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "input_schema": {
    "type": "object",
    "properties": { "tonnage_capacity": { "type": "number" }, "...": {} },
    "required": ["tonnage_capacity", "us_state_location", "site_accessibility"],
    "additionalProperties": false
  },
  "required_fields": ["tonnage_capacity", "us_state_location", "site_accessibility"]
}

calculate_quote

Calculate a verified quote once every required field is collected.

ArgumentTypeNotes
platformstringgohighlevel
external_idstringthe business's platform account ID
service_typestringmust match a configured engine
inputsobjectkeys & types defined by input_schema

Success (structured content)

json
{
  "engine_used": "Residential AC Replacement",
  "engine_id": "b7c1e0a2-...",
  "service_type": "AC Replacement",
  "tenant_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "total": 6416.25,
  "breakdown": {
    "line_items": [
      { "key": "equipment", "label": "Base Equipment",     "amount": 4900.0 },
      { "key": "labor",     "label": "Installation Labor",  "amount": 1000.0 }
    ],
    "modifiers": [],
    "subtotal": 5900.0,
    "tax": 516.25,
    "tax_rate": 0.0875,
    "total": 6416.25
  }
}

Schema-gate workflow

Use this loop so the agent never invents missing job details.

get_quote_schema collect required_fieldsask the customer calculate_quote VALIDATION_ERROR → missing_fields
  1. Call get_quote_schema with platform, external_id, service_type.
  2. Collect every value in required_fields from the customer.
  3. Call calculate_quote with the complete inputs.
  4. If it returns VALIDATION_ERROR, read details.missing_fields, ask those questions, and retry.

Errors

MCP tool errors return isError: true with a structured payload. The REST API returns the same body with an HTTP status.

CodeWhenREST status
TENANT_NOT_FOUNDUnknown platform + external_id — the business is not onboarded404
ENGINE_NOT_FOUNDThe service_type is not configured for that tenant404
VALIDATION_ERRORMissing or invalid inputsdetails.missing_fields lists what to ask for422
CONFIG_INVALIDThe tenant's engine JSON is malformed (Quotix is alerted)500

Error payload

json
{
  "error": "VALIDATION_ERROR",
  "message": "Required quote inputs are missing or invalid.",
  "details": { "missing_fields": ["site_accessibility"] }
}

Also expect standard 401 Unauthorized when the Bearer token is missing or wrong.

Worked example

The Empire HVAC NY pilot tenant. Copy these values to test end to end.

FieldValue
platformgohighlevel
external_idghl_sub_ny_445
service_typeAC Replacement
tenant_ida1b2c3d4-e5f6-7890-abcd-ef1234567890

Request — calculate_quote

json
{
  "platform": "gohighlevel",
  "external_id": "ghl_sub_ny_445",
  "service_type": "AC Replacement",
  "inputs": {
    "tonnage_capacity": 3,
    "us_state_location": "New York",
    "site_accessibility": "Attic - pull-down access"
  }
}

Result

LineFormulaAmount
Base Equipment2500 + (3 × 800)$4,900.00
Installation Labor8 × 125$1,000.00
Subtotal$5,900.00
Tax5900 × 0.0875$516.25
Total$6,416.25
Change site_accessibility to "Rooftop - ladder access" and a +$350 modifier is applied — a new subtotal, instantly, from the same rules.

Pricing engines

Each service_type is a JSON engine: an input_schema (what to collect) and a calculation (how to price). Engines are data — new service types are a config change, not a code deploy.

json
{
  "schema_version": "1.0",
  "display_name": "Residential AC Replacement",
  "shareable": true,
  "input_schema": {
    "type": "object",
    "properties": {
      "tonnage_capacity":   { "type": "number", "minimum": 1, "maximum": 10 },
      "us_state_location":  { "type": "string", "enum": ["New York", "New Jersey", "Connecticut"] },
      "site_accessibility": { "type": "string", "enum": ["Attic - pull-down access", "Rooftop - ladder access", "..."] }
    },
    "required": ["tonnage_capacity", "us_state_location", "site_accessibility"],
    "additionalProperties": false
  },
  "calculation": {
    "line_items": [
      { "key": "equipment", "label": "Base Equipment",
        "formula": "base_equipment + (tonnage_capacity * ton_multiplier)",
        "vars": { "base_equipment": 2500, "ton_multiplier": 800 } },
      { "key": "labor", "label": "Installation Labor",
        "formula": "labor_hours * labor_rate",
        "vars": { "labor_hours": 8, "labor_rate": 125 } }
    ],
    "modifiers": [
      { "when": { "field": "site_accessibility", "equals": "Rooftop - ladder access" },
        "add": 350, "label": "Rooftop access surcharge" }
    ],
    "tax": { "rate": 0.0875 }
  }
}
PartMeaning
input_schemaStandard JSON Schema. Also returned by get_quote_schema and shareable with GHL / CloseBot so questions aren't hard-coded.
line_items[].formulaArithmetic only — + - * /, numeric literals, and names from vars + the customer inputs. No functions, no arbitrary code.
modifiers[]Conditional surcharges: when a field equals a value, add an amount.
tax.rateApplied to the subtotal (line items + modifiers).

REST API

The same pricing brain over plain HTTP, for clients that don't speak MCP. Same Bearer key.

Method & pathAuthPurpose
GET /healthLiveness + database connectivity
GET /v1/statusBearerConfirm your API key works
POST /v1/quotes/calculateBearerVerified quote — body is the calculate_quote payload
GET /v1/engines/schemaBearerInput schema — query platform, external_id, service_type
GET /v1/tenants/{tenant_id}/enginesBearerList a tenant's configured services
bash
curl -sS -X POST https://mcp.quotix.ai/v1/quotes/calculate \
  -H "Authorization: Bearer $QUOTIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "platform": "gohighlevel",
    "external_id": "ghl_sub_ny_445",
    "service_type": "AC Replacement",
    "inputs": { "tonnage_capacity": 3, "us_state_location": "New York",
                "site_accessibility": "Attic - pull-down access" }
  }'

Interactive API reference (OpenAPI / Swagger UI): https://mcp.quotix.ai/docs

Request access

Onboarding is done by the Quotix team (no self-serve yet). To get an API key and your tenant configured, send us:

WhatWhy
Company name & primary contactCreates your tenant record
GoHighLevel sub-account ID (and CloseBot bot ID if used)The external_id that routes requests to you
Service types to configuree.g. AC Replacement, Rooftop Installation, Ductwork
Signed-off pricing formulas per serviceLine items, modifiers, tax rate — the deterministic rules
Required customer inputs per serviceThe fields your chat must collect
Regions / enumse.g. NY, NJ, CT and any option lists
Staging or production keyWe issue keys per environment

FAQ

Why can the total differ from the Quotix website form?

Expected in V1. The website form builder and this chat-pricing service are separate systems until they're merged. This service is the source of truth for agent-driven quotes.

Can we add a new service type without a developer?

Yes. A service type is a JSON engine (schema + calculation). Add the file and re-seed — no application redeploy.

Is the API key safe to share?

Only with trusted systems (your n8n instance, your team). Treat it like a password. Production and staging use different keys.

Does Quotix generate the PDF / write back to GoHighLevel?

No. Quotix returns price JSON only. PDF proposals and GHL write-back are handled in your n8n workflow (GoHighLevel has its own MCP server for write-back).

Is there an LLM in the pricing path?

No. The agent collects inputs; Quotix validates them against the schema and runs fixed arithmetic. Same inputs → same price, every time.