{
  "version": 1,
  "sdk_version": "0.20.0",
  "path": "/functions/v1/mcp",
  "auth": {
    "type": "oauth",
    "issuer": "https://ikisxgnworeueyqydtox.supabase.co/auth/v1",
    "accepted_audiences": [
      "authenticated"
    ]
  },
  "mcp": {
    "server": {
      "name": "lavo-crm",
      "version": "1.12.0",
      "title": "Lavo CRM"
    },
    "tools": [
      {
        "name": "list_my_accounts",
        "title": "List my Lavo CRM accounts",
        "description": "List every Lavo CRM tenant account (workspace) the signed-in user belongs to — e.g. their real business plus any demo sandbox. Use this whenever the user asks about their accounts / workspaces / tenants, or names a specific one like 'my Snappy's account', 'the sandbox', or 'my real account'. The returned `id` (also aliased as `company_id`) is the value to pass as `company_id` to other tools. This is NOT a list of customer records — for B2B customer/contact records use `list_customers` instead.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {}
        },
        "outputSchema": null
      },
      {
        "name": "get_customer",
        "title": "Get customer",
        "description": "Fetch a single Lavo CRM customer/contact record by ID from ONE account. Returns name, email, phones, address, status, notes, and type. If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`; otherwise the caller's default account is used.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "customer_id": {
              "type": "string",
              "minLength": 1,
              "description": "Customer UUID"
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`. Omit to use the caller's default account.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "customer_id"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "list_customers",
        "title": "List / search customers",
        "description": "Search customer/contact records within ONE Lavo CRM account by person name, email, or phone. Returns up to `limit` results (default 20). If the user names a specific account/workspace/tenant (e.g. 'Snappy's', 'the sandbox', 'my real account'), first call `list_my_accounts` and pass the matching id as `company_id`; otherwise the caller's default account is used.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "query": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "description": "Search term (name, email, or phone)"
            },
            "limit": {
              "description": "Max results (default 20)",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`. Omit to use the caller's default account.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "query"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "get_property",
        "title": "Get property",
        "description": "Fetch a service property (address record) with full detail including size, features, and owning customer. If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`; otherwise the caller's default account is used.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "property_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
              "description": "Property UUID"
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`. Omit to use the caller's default account.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "property_id"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "list_properties",
        "title": "List / search service properties",
        "description": "List service properties (addresses) within ONE Lavo CRM account. Filter by customer_id to see all properties for one customer, or by address search string. If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`; otherwise the caller's default account is used.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "customer_id": {
              "description": "Only return properties belonging to this customer",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "query": {
              "description": "Search term matched against address, city, zip, or property name",
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            },
            "limit": {
              "description": "Max results (default 20)",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`. Omit to use the caller's default account.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        },
        "outputSchema": null
      },
      {
        "name": "get_quote",
        "title": "Get quote",
        "description": "Fetch a Lavo CRM quote with its line items and customer info from ONE account. If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`; otherwise the caller's default account is used.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "quote_id": {
              "type": "string",
              "minLength": 1,
              "description": "Quote UUID"
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`. Omit to use the caller's default account.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "quote_id"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "list_quotes",
        "title": "List quotes",
        "description": "List Lavo CRM quotes within ONE account, with optional status and customer filters. Supports pagination. If the user names a specific account/workspace/tenant (e.g. 'Snappy's', 'the sandbox'), first call `list_my_accounts` and pass the matching id as `company_id`; otherwise the caller's default account is used.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "status": {
              "description": "Filter by status (e.g. draft, sent, accepted)",
              "type": "string"
            },
            "customer_id": {
              "description": "Filter by customer UUID",
              "type": "string"
            },
            "limit": {
              "description": "Max results (default 25)",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "offset": {
              "description": "Offset for pagination (default 0)",
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`. Omit to use the caller's default account.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        },
        "outputSchema": null
      },
      {
        "name": "get_job",
        "title": "Get job",
        "description": "Fetch a job with customer, property, visits, and any linked invoices. If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`; otherwise the caller's default account is used.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "job_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
              "description": "Job UUID"
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`. Omit to use the caller's default account.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "job_id"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "list_jobs",
        "title": "List jobs",
        "description": "List jobs within ONE Lavo CRM account. Optionally filter by status, customer, or scheduled date range. Returns up to `limit` results (default 20). If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`; otherwise the caller's default account is used.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "status": {
              "description": "Job status filter (e.g. 'needs_scheduling', 'visit_scheduled', 'needs_invoicing', 'invoiced', 'paid')",
              "type": "string"
            },
            "customer_id": {
              "description": "Only jobs for this customer",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "scheduled_from": {
              "description": "ISO date YYYY-MM-DD, inclusive lower bound on scheduled_date",
              "type": "string"
            },
            "scheduled_to": {
              "description": "ISO date YYYY-MM-DD, inclusive upper bound on scheduled_date",
              "type": "string"
            },
            "limit": {
              "description": "Max results (default 20)",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`. Omit to use the caller's default account.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        },
        "outputSchema": null
      },
      {
        "name": "list_visits",
        "title": "List visits (schedule)",
        "description": "List scheduled visits within ONE Lavo CRM account. Optionally filter by date range, status, customer, job, or assigned tech/user. Great for 'what's on my schedule today/this week' questions. Returns up to `limit` results (default 50). If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`; otherwise the caller's default account is used.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "date_from": {
              "description": "ISO date YYYY-MM-DD lower bound on visit_date",
              "type": "string"
            },
            "date_to": {
              "description": "ISO date YYYY-MM-DD upper bound on visit_date",
              "type": "string"
            },
            "status": {
              "description": "Visit status filter (e.g. 'scheduled', 'in_progress', 'completed', 'cancelled', 'skipped')",
              "type": "string"
            },
            "customer_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "job_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "assigned_user_id": {
              "description": "Filter to a specific staff user",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "assigned_technician_id": {
              "description": "Filter to a specific technician record",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "limit": {
              "description": "Max results (default 50)",
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`. Omit to use the caller's default account.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        },
        "outputSchema": null
      },
      {
        "name": "get_invoice",
        "title": "Get invoice",
        "description": "Fetch an invoice with line items, customer, and payment history. If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`; otherwise the caller's default account is used.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "invoice_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
              "description": "Invoice UUID"
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`. Omit to use the caller's default account.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "invoice_id"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "list_invoices",
        "title": "List invoices",
        "description": "List invoices within ONE Lavo CRM account. Optionally filter by status (e.g. 'draft', 'sent', 'paid', 'overdue'), customer, job, or issue-date range. Returns up to `limit` results (default 20). If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`; otherwise the caller's default account is used.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "status": {
              "description": "Invoice status filter",
              "type": "string"
            },
            "customer_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "job_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "issued_from": {
              "description": "ISO date YYYY-MM-DD lower bound on issue_date",
              "type": "string"
            },
            "issued_to": {
              "description": "ISO date YYYY-MM-DD upper bound on issue_date",
              "type": "string"
            },
            "limit": {
              "description": "Max results (default 20)",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`. Omit to use the caller's default account.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        },
        "outputSchema": null
      },
      {
        "name": "list_requests",
        "title": "List inbound requests / leads",
        "description": "List inbound request-form submissions (leads) within ONE Lavo CRM account. Filter by status ('new'|'viewed'|'reviewed'|'converted'|'archived'), customer, or created-date range. Returns up to `limit` results (default 25, newest first). If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "status": {
              "description": "Request status filter",
              "type": "string"
            },
            "customer_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "date_from": {
              "description": "ISO date/time lower bound on created_at",
              "type": "string"
            },
            "date_to": {
              "description": "ISO date/time upper bound on created_at",
              "type": "string"
            },
            "limit": {
              "description": "Max results (default 25)",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        },
        "outputSchema": null
      },
      {
        "name": "get_request",
        "title": "Get inbound request",
        "description": "Fetch a single inbound request (lead) by ID, including the raw form submission data and any conversion links.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "request_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
              "description": "Request UUID"
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "request_id"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "list_messages",
        "title": "List SMS messages",
        "description": "Read SMS message history within ONE Lavo CRM account. Filter by customer, direction ('inbound'|'outbound'), or date range. Read-only — this does NOT send anything. Returns up to `limit` results (default 50, newest first). If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "customer_id": {
              "description": "Filter to one customer's thread",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "direction": {
              "type": "string",
              "enum": [
                "inbound",
                "outbound"
              ]
            },
            "date_from": {
              "description": "ISO date/time lower bound on created_at",
              "type": "string"
            },
            "date_to": {
              "description": "ISO date/time upper bound on created_at",
              "type": "string"
            },
            "limit": {
              "description": "Max results (default 50)",
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        },
        "outputSchema": null
      },
      {
        "name": "search_everything",
        "title": "Global search",
        "description": "Search across customers, quotes, jobs, and invoices in ONE Lavo CRM account for a single term. Matches customer name/email/phone, quote/job/invoice numbers, and job titles. Returns a small top-N per entity for fast triage — follow up with `get_*` for full detail. If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "query": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "description": "Search term"
            },
            "limit_per_type": {
              "description": "Max results per entity type (default 5)",
              "type": "integer",
              "minimum": 1,
              "maximum": 25
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "query"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "search",
        "title": "Search Lavo CRM",
        "description": "Search across customers, quotes, jobs, and invoices in ONE Lavo CRM account and return a flat, ranked list of results. Each result has an opaque `id` — pass it to the `fetch` tool to retrieve the full record. If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "query": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "description": "Search term"
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`. Omit to use the caller's default account.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "query"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "fetch",
        "title": "Fetch a Lavo CRM record",
        "description": "Retrieve the full detail of a single Lavo CRM record using an opaque `id` returned by the `search` tool (format `customer:<uuid>`, `quote:<uuid>`, `job:<uuid>`, or `invoice:<uuid>`). If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100,
              "description": "Opaque record id from `search`, e.g. `customer:2f1c…` or `invoice:9ab3…`"
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`. Omit to use the caller's default account.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "id"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "list_photos",
        "title": "List project photos",
        "description": "List project photos (before/after job photos) attached to a job, quote, or invoice in ONE Lavo CRM account. Returns structured metadata (image_url, tag such as 'before'/'after', caption, ordering) plus a downloadable resource_link for each photo. Set include_image_data=true to also attach the FIRST FEW photos as REAL INLINE IMAGE DATA you can place directly into a flyer or postcard without fetching any URL — do this whenever you need the actual pixels, and narrow the set first with `tag` and `limit` (max 6 photos are inlined per call). Provide exactly one of job_id, quote_id, or invoice_id. Use this after finding the job via get_schedule / list_visits / get_job. If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "job_id": {
              "description": "Return photos attached to this job",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "quote_id": {
              "description": "Return photos attached to this quote",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "invoice_id": {
              "description": "Return photos attached to this invoice",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "tag": {
              "description": "Only return photos with this tag, e.g. 'before' or 'after' (case-insensitive)",
              "type": "string",
              "minLength": 1,
              "maxLength": 60
            },
            "limit": {
              "description": "Max photos to return (default 50)",
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            },
            "include_image_data": {
              "description": "Attach the actual image bytes inline (base64) for up to the first 6 photos. Use when you need to place the real photos into a generated asset.",
              "type": "boolean"
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`. Omit to use the caller's default account.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        },
        "outputSchema": null
      },
      {
        "name": "get_company_branding",
        "title": "Company branding",
        "description": "Return the account's branding and mailing details: the company logo (attached as REAL IMAGE DATA you can place directly into a flyer, postcard, or document — plus a public URL and a resource_link), brand primary/secondary colors, website URL, public review link, and the company's mailing/contact address, phone, and email. Use this whenever the user asks to make something branded or asks for 'our logo' / 'our colors' / 'our address'. If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "include_image_data": {
              "description": "Attach the logo as inline image data (default true). Set false for a metadata-only response.",
              "type": "boolean"
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        },
        "outputSchema": null
      },
      {
        "name": "get_dashboard_snapshot",
        "title": "Dashboard snapshot",
        "description": "Return a compact 'state of the business today' snapshot for ONE Lavo CRM account: today's payments collected, quotes currently out (status=sent), visits scheduled today, open invoice count and total AR outstanding, and new (unviewed) inbound requests. If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        },
        "outputSchema": null
      },
      {
        "name": "get_schedule",
        "title": "Get schedule (grouped by day)",
        "description": "Return visits for a preset date range ('today'|'tomorrow'|'this_week'|'next_week'|'next_7_days') or an explicit date_from/date_to range, grouped by day. Optionally filter to one tech. Great for 'what's on the calendar this week' questions. If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "preset": {
              "description": "Convenience date range. Ignored if date_from/date_to provided.",
              "type": "string",
              "enum": [
                "today",
                "tomorrow",
                "this_week",
                "next_week",
                "next_7_days"
              ]
            },
            "date_from": {
              "description": "ISO date YYYY-MM-DD",
              "type": "string"
            },
            "date_to": {
              "description": "ISO date YYYY-MM-DD",
              "type": "string"
            },
            "assigned_user_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "assigned_technician_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        },
        "outputSchema": null
      },
      {
        "name": "create_customer",
        "title": "Create customer",
        "description": "Create a new customer/contact in ONE Lavo CRM account. Sets display_name automatically from is_company + company_name OR first_name + last_name. Does NOT send anything to the customer. Does NOT set marketing/SMS consent — the customer must opt in through the normal in-app flow. If the user names a specific account/workspace/tenant, first call `list_my_accounts` and pass the matching id as `company_id`.",
        "annotations": {
          "readOnlyHint": false,
          "destructiveHint": false,
          "idempotentHint": false,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "is_company": {
              "description": "True if the customer is a business rather than an individual",
              "type": "boolean"
            },
            "first_name": {
              "type": "string",
              "maxLength": 100
            },
            "last_name": {
              "type": "string",
              "maxLength": 100
            },
            "company_name": {
              "type": "string",
              "maxLength": 200
            },
            "email": {
              "type": "string",
              "maxLength": 200,
              "format": "email",
              "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
            },
            "mobile_phone": {
              "type": "string",
              "maxLength": 40
            },
            "work_phone": {
              "type": "string",
              "maxLength": 40
            },
            "home_phone": {
              "type": "string",
              "maxLength": 40
            },
            "customer_type": {
              "type": "string",
              "enum": [
                "residential",
                "commercial"
              ]
            },
            "source": {
              "description": "Where this lead came from (e.g. 'referral', 'google')",
              "type": "string",
              "maxLength": 100
            },
            "notes": {
              "type": "string",
              "maxLength": 4000
            },
            "billing_address_line1": {
              "type": "string",
              "maxLength": 200
            },
            "billing_address_line2": {
              "type": "string",
              "maxLength": 200
            },
            "billing_city": {
              "type": "string",
              "maxLength": 100
            },
            "billing_state": {
              "type": "string",
              "maxLength": 50
            },
            "billing_zip_code": {
              "type": "string",
              "maxLength": 20
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        },
        "outputSchema": null
      },
      {
        "name": "update_customer",
        "title": "Update customer",
        "description": "Update basic fields on an existing customer. Only touches name/contact/address/notes/status/source. Does NOT modify marketing or SMS consent, notification preferences, portal tokens, or provider (Stripe/Square/QBO) IDs — those still change only via the in-app flow. Recomputes display_name automatically. Does NOT send anything to the customer.",
        "annotations": {
          "readOnlyHint": false,
          "destructiveHint": false,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "customer_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "is_company": {
              "type": "boolean"
            },
            "first_name": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 100
                },
                {
                  "type": "null"
                }
              ]
            },
            "last_name": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 100
                },
                {
                  "type": "null"
                }
              ]
            },
            "company_name": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 200
                },
                {
                  "type": "null"
                }
              ]
            },
            "email": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 200,
                  "format": "email",
                  "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                },
                {
                  "type": "null"
                }
              ]
            },
            "mobile_phone": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 40
                },
                {
                  "type": "null"
                }
              ]
            },
            "work_phone": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 40
                },
                {
                  "type": "null"
                }
              ]
            },
            "home_phone": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 40
                },
                {
                  "type": "null"
                }
              ]
            },
            "customer_type": {
              "type": "string",
              "enum": [
                "residential",
                "commercial"
              ]
            },
            "source": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 100
                },
                {
                  "type": "null"
                }
              ]
            },
            "notes": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 8000
                },
                {
                  "type": "null"
                }
              ]
            },
            "billing_address_line1": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 200
                },
                {
                  "type": "null"
                }
              ]
            },
            "billing_address_line2": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 200
                },
                {
                  "type": "null"
                }
              ]
            },
            "billing_city": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 100
                },
                {
                  "type": "null"
                }
              ]
            },
            "billing_state": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 50
                },
                {
                  "type": "null"
                }
              ]
            },
            "billing_zip_code": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 20
                },
                {
                  "type": "null"
                }
              ]
            },
            "status": {
              "type": "string",
              "maxLength": 40
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "customer_id"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "add_customer_note",
        "title": "Append internal customer note",
        "description": "Append an internal note to a customer's `notes` field with a timestamp and 'via MCP' attribution. This is an INTERNAL note only — it is NOT sent to the customer as SMS, email, or push. Preserves existing notes (never overwrites).",
        "annotations": {
          "readOnlyHint": false,
          "destructiveHint": false,
          "idempotentHint": false,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "customer_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "note": {
              "type": "string",
              "minLength": 1,
              "maxLength": 4000,
              "description": "Internal note text to append"
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "customer_id",
            "note"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "add_tag_to_customer",
        "title": "Add tag to customer",
        "description": "Attach a tag to a customer. Pass either an existing tag_id, or a tag_name to look up (case-insensitive). If tag_name doesn't exist and `create_if_missing` is true (default), a new tag is created in this account. Idempotent: re-adding an existing tag is a no-op.",
        "annotations": {
          "readOnlyHint": false,
          "destructiveHint": false,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "customer_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "tag_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "tag_name": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            },
            "create_if_missing": {
              "description": "If tag_name doesn't exist, create it. Default true.",
              "type": "boolean"
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "customer_id"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "remove_tag_from_customer",
        "title": "Remove tag from customer",
        "description": "Detach a tag from a customer. Pass either tag_id or tag_name (case-insensitive). Does NOT delete the tag itself — only the assignment. Idempotent: removing a tag that isn't assigned is a no-op.",
        "annotations": {
          "readOnlyHint": false,
          "destructiveHint": true,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "customer_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "tag_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "tag_name": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "customer_id"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "create_quote_draft",
        "title": "Create quote (draft)",
        "description": "Create a DRAFT quote (status='draft'). Never sent to the customer — the human still opens it in the Lavo CRM app to review, add tax/deposits, and send. Requires a property_address; optionally links to an existing customer_id and property_id. Line items are stored as services on the quote so it renders like any in-app quote. Use `add_line_item_to_quote` and `apply_discount_to_quote` to iterate before the human opens the draft.",
        "annotations": {
          "readOnlyHint": false,
          "destructiveHint": false,
          "idempotentHint": false,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "customer_id": {
              "description": "Existing customer to link; omit for a walk-in draft.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "property_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "property_address": {
              "description": "Street address for the property. Required unless a valid property_id is passed (in which case it's backfilled from the stored property record).",
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            },
            "property_city": {
              "type": "string",
              "maxLength": 100
            },
            "property_state": {
              "type": "string",
              "maxLength": 50
            },
            "property_zip": {
              "type": "string",
              "maxLength": 20
            },
            "line_items": {
              "minItems": 1,
              "maxItems": 50,
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 1000
                  },
                  "quantity": {
                    "default": 1,
                    "type": "number",
                    "exclusiveMinimum": 0
                  },
                  "unit_price": {
                    "type": "number",
                    "minimum": 0
                  }
                },
                "required": [
                  "name",
                  "unit_price"
                ]
              },
              "description": "Line items — {name, quantity, unit_price}"
            },
            "notes": {
              "description": "Customer-visible quote notes",
              "type": "string",
              "maxLength": 4000
            },
            "internal_notes": {
              "description": "Staff-only notes",
              "type": "string",
              "maxLength": 4000
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "line_items"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "add_line_item_to_quote",
        "title": "Add line item to draft quote",
        "description": "Append a line item to a DRAFT quote's custom_line_items and recompute total_price (services subtotal + custom items − package discount, no tax). Rejects quotes that aren't in status='draft' — edits to sent/accepted quotes must happen in-app so downstream side effects run correctly.",
        "annotations": {
          "readOnlyHint": false,
          "destructiveHint": false,
          "idempotentHint": false,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "quote_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "name": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            },
            "description": {
              "type": "string",
              "maxLength": 1000
            },
            "quantity": {
              "default": 1,
              "type": "number",
              "exclusiveMinimum": 0
            },
            "unit_price": {
              "type": "number",
              "minimum": 0
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "quote_id",
            "name",
            "unit_price"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "apply_discount_to_quote",
        "title": "Apply package discount to draft quote",
        "description": "Apply a package-level discount (fixed dollar amount OR percent of subtotal) to a DRAFT quote and recompute total_price. Rejects quotes not in status='draft' and quotes with discount_locked=true. Pass either amount OR percent, not both. Pass amount=0 (or percent=0) to clear the discount.",
        "annotations": {
          "readOnlyHint": false,
          "destructiveHint": false,
          "idempotentHint": true,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "quote_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "amount": {
              "description": "Fixed dollar discount",
              "type": "number",
              "minimum": 0
            },
            "percent": {
              "description": "Percent of subtotal_before_discount",
              "type": "number",
              "minimum": 0,
              "maximum": 100
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "quote_id"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "convert_quote_to_job",
        "title": "Convert accepted quote to job",
        "description": "Create a job (status='needs_scheduling') from an already-ACCEPTED quote that isn't linked to a job yet. Does NOT send any customer notification. TWO-PHASE: call WITHOUT confirm_token to get a preview and a short-lived confirm_token (5 min TTL). Call again with the same args PLUS confirm_token to actually create the job. Copies tax/deposit/terms data from the quote onto the job.",
        "annotations": {
          "readOnlyHint": false,
          "destructiveHint": false,
          "idempotentHint": false,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "quote_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "title": {
              "description": "Optional job title; defaults to a summary of the quote's services.",
              "type": "string",
              "maxLength": 200
            },
            "description": {
              "type": "string",
              "maxLength": 2000
            },
            "confirm_token": {
              "description": "Confirmation token from the preview response. Required to actually create the job.",
              "type": "string"
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "quote_id"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "schedule_visit",
        "title": "Schedule a visit (internal, no customer notification)",
        "description": "Schedule a visit on an existing job by inserting directly into the visits table. Does NOT send any confirmation SMS, email, or push — the customer is not notified. To actually notify the customer, schedule the visit inside the Lavo CRM app instead. Also flips the job to status='visit_scheduled' if it's currently 'needs_scheduling'.",
        "annotations": {
          "readOnlyHint": false,
          "destructiveHint": false,
          "idempotentHint": false,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "job_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "visit_date": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "start_time": {
              "description": "HH:MM (24h)",
              "type": "string",
              "pattern": "^\\d{2}:\\d{2}(:\\d{2})?$"
            },
            "end_time": {
              "type": "string",
              "pattern": "^\\d{2}:\\d{2}(:\\d{2})?$"
            },
            "duration_hours": {
              "type": "number",
              "exclusiveMinimum": 0,
              "maximum": 24
            },
            "assigned_user_id": {
              "description": "Staff user to assign (from profiles).",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "assigned_technician_id": {
              "description": "Technician record to assign.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "crew_assigned": {
              "type": "string",
              "maxLength": 200
            },
            "notes": {
              "description": "Customer-visible visit notes.",
              "type": "string",
              "maxLength": 4000
            },
            "internal_notes": {
              "type": "string",
              "maxLength": 4000
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "job_id",
            "visit_date"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "reschedule_visit",
        "title": "Reschedule a visit (internal, no customer notification)",
        "description": "Change the date/time or reassign a scheduled visit by updating the visits row directly. Does NOT send a reschedule SMS, email, or push. Only visits in status='scheduled' can be moved via MCP — completed/cancelled visits are read-only here.",
        "annotations": {
          "readOnlyHint": false,
          "destructiveHint": false,
          "idempotentHint": false,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "visit_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "visit_date": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "start_time": {
              "type": "string",
              "pattern": "^\\d{2}:\\d{2}(:\\d{2})?$"
            },
            "end_time": {
              "type": "string",
              "pattern": "^\\d{2}:\\d{2}(:\\d{2})?$"
            },
            "duration_hours": {
              "type": "number",
              "exclusiveMinimum": 0,
              "maximum": 24
            },
            "assigned_user_id": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "uuid",
                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                },
                {
                  "type": "null"
                }
              ]
            },
            "assigned_technician_id": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "uuid",
                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                },
                {
                  "type": "null"
                }
              ]
            },
            "crew_assigned": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 200
                },
                {
                  "type": "null"
                }
              ]
            },
            "notes": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 4000
                },
                {
                  "type": "null"
                }
              ]
            },
            "internal_notes": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 4000
                },
                {
                  "type": "null"
                }
              ]
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "visit_id"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "create_invoice_from_job",
        "title": "Create draft invoice from job (internal, no send)",
        "description": "Create a DRAFT invoice attached to an existing job. Line items default to a single summary line at the job's estimated amount, or you can pass explicit {description, quantity, unit_price} items. Always status='draft' — nothing is sent to the customer. Totals are computed by the invoice_totals trigger. The human still opens the draft in the Lavo CRM app to review, set due date/tax details, and send.",
        "annotations": {
          "readOnlyHint": false,
          "destructiveHint": false,
          "idempotentHint": false,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "job_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "due_date": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "notes": {
              "type": "string",
              "maxLength": 4000
            },
            "line_items": {
              "description": "Optional explicit line items. Defaults to a single 'Services rendered' line at job.estimated_amount.",
              "maxItems": 50,
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "description": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  },
                  "quantity": {
                    "default": 1,
                    "type": "number",
                    "exclusiveMinimum": 0
                  },
                  "unit_price": {
                    "type": "number",
                    "minimum": 0
                  },
                  "is_taxable": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "description",
                  "unit_price"
                ]
              }
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "job_id"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "record_offline_payment",
        "title": "Record an offline payment (cash / check, no receipt)",
        "description": "Record a manual cash or check payment against an invoice by inserting a payments row directly. Does NOT send a receipt SMS or email — the customer is not notified. The invoice status, amount_paid, and (if fully paid) the linked job status are updated automatically by DB triggers. To send a receipt, record the payment in the Lavo CRM app instead.",
        "annotations": {
          "readOnlyHint": false,
          "destructiveHint": false,
          "idempotentHint": false,
          "openWorldHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "invoice_id": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "amount": {
              "type": "number",
              "exclusiveMinimum": 0,
              "description": "Amount received, in the account's currency."
            },
            "payment_method": {
              "type": "string",
              "enum": [
                "cash",
                "check"
              ],
              "description": "Only offline methods. Card/ACH/etc. must go through the app so the processor is charged."
            },
            "payment_date": {
              "description": "Defaults to today.",
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "reference": {
              "description": "Check number or cash reference.",
              "type": "string",
              "maxLength": 200
            },
            "notes": {
              "type": "string",
              "maxLength": 1000
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "invoice_id",
            "amount",
            "payment_method"
          ]
        },
        "outputSchema": null
      },
      {
        "name": "quote_house_washing_price",
        "title": "Suggest House Washing price for an address",
        "description": "Run the same House Washing pricing flow the in-app House Assistant uses: DB-first (uses stored square_footage / stories / exterior / property value from the customer's property record when available), then RentCast for anything missing, then the company's configured SmartScale / property-value multipliers. Returns a suggested price. Does NOT modify any quote — after presenting the price to the user, call add_line_item_to_quote with the returned suggested_price if they approve. Pass property_id (preferred) or customer_id so this matches the price the in-app assistant would show.",
        "annotations": {
          "readOnlyHint": true,
          "idempotentHint": true,
          "openWorldHint": true,
          "destructiveHint": false
        },
        "inputSchema": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "address": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500,
              "description": "Street address to price (e.g. '123 Main St, Austin, TX')."
            },
            "property_id": {
              "description": "Stored property to load defaults from (DB-first, matches in-app House Assistant).",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "customer_id": {
              "description": "If passed without property_id, resolves the customer's property whose address matches, else their primary property.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "quote_id": {
              "description": "Optional: link the pricing run to an existing DRAFT quote. When passed, the property record on that quote is refreshed with the looked-up RentCast data (same behavior as the in-app assistant).",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "overrides": {
              "description": "Optional user-confirmed property values. These win over DB and RentCast.",
              "type": "object",
              "properties": {
                "square_footage": {
                  "type": "number",
                  "exclusiveMinimum": 0
                },
                "stories": {
                  "type": "number",
                  "exclusiveMinimum": 0
                },
                "exterior_material": {
                  "type": "string",
                  "maxLength": 60
                },
                "property_type": {
                  "type": "string",
                  "maxLength": 60
                },
                "lot_size": {
                  "description": "Lot size in sqft.",
                  "type": "number",
                  "exclusiveMinimum": 0
                },
                "year_built": {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                "property_value": {
                  "type": "number",
                  "minimum": 0
                }
              }
            },
            "company_id": {
              "description": "Target account UUID from `list_my_accounts`.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "required": [
            "address"
          ]
        },
        "outputSchema": null
      }
    ]
  }
}
