Skip to main content
Glama

DeepLedger QuickBooks MCP Server for ChatGPT, Claude & AI

qbSendEmail

Destructive

QuickBooks: email a sales document (Invoice, Estimate, SalesReceipt, CreditMemo, RefundReceipt) to the customer. The ONLY tool that emails a customer: recording never sends, and emailStatus "NeedToSend" only queues it for a person. An email cannot be unsent: confirm with the user first (needs confirm:true unless your app asks the user itself), never send to test or re-send to be sure. Needs documentType and documentId. Delivered only when delivered:true with deliveryTime. Voided documents and missing addresses are refused.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "documentType": "<documentType>",
      "documentId": "<documentId>"
    },
    "name": "qbSendEmail"
  }
}

Input Schema

NameRequiredDescriptionDefault
sendToNoOverrides AND permanently overwrites the stored address; omit to use it.
confirmNotrue once the user confirmed this exact call.
companyIdNo
documentIdYesNUMERIC id (qbFetchTransactions), not the document number.
documentTypeYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed7 schema fields changed
    • addedInput schema / $schema
      Added value: +"https://json-schema.org/draft/2020-12/schema"
    • addedInput schema / properties / companyId
      Added value: +{
      +  "type": "string"
      +}
    • addedInput schema / properties / confirm
      Added value: +{
      +  "default": false,
      +  "description": "true once the user confirmed this exact call.",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / documentId / description
      Previous value: -"The NUMERIC id (qbFetchTransactions), not the document number; it must be of documentType."New value: +"NUMERIC id (qbFetchTransactions), not the document number."
    • removedInput schema / properties / documentType / description
      Removed value: -"Sales document type (purchase records cannot be emailed)."
    • changedInput schema / properties / sendTo / description
      Previous value: -"Deliver here instead of the stored address. It permanently OVERWRITES the document's stored address, so later sends go here too. Omit to use the stored one."New value: +"Overrides AND permanently overwrites the stored address; omit to use it."
    • changedOutput schema / (root)
      Previous value: -{
      -  "additionalProperties": false,
      -  "properties": {
      -    "addressOverwritten": {
      -      "description": "TRUE when sendTo replaced the address stored on the document. The change is permanent.",
      -      "type": "boolean"
      -    },
      -    "company": {
      -      "additionalProperties": false,
      -      "description": "The company this result came from. Read it back to the user by name.",
      -      "properties": {
      -        "name": {
      -          "description": "DeepLedger client name.",
      -          "type": "string"
      -        },
      -        "organizationId": {
      -          "description": "DeepLedger organization id the call operated on.",
      -          "type": "string"
      -        },
      -        "qbCompanyName": {
      -          "description": "QuickBooks company name, when connected.",
      -          "type": "string"
      -        },
      -        "setAt": {
      -          "description": "When the active company was last set (source \"active\" only).",
      -          "type": "string"
      -        },
      -        "setBy": {
      -          "description": "Who last set the active company (source \"active\" only).",
      -          "enum": [
      -            "mcp",
      -            "portal",
      -            "backfill"
      -          ],
      -          "type": "string"
      -        },
      -        "source": {
      -          "description": "How the company was chosen: \"active\" = the user's switchable active company; \"pinned\" = fixed by the credential; \"header\" = fixed by X-Organization-Id; \"system\" = an unattended routine credential.",
      -          "enum": [
      -            "system",
      -            "header",
      -            "pinned",
      -            "active"
      -          ],
      -          "type": "string"
      -        }
      -      },
      -      "required": [
      -        "organizationId"
      -      ],
      -      "type": "object"
      -    },
      -    "customerName": {
      -      "type": "string"
      -    },
      -    "delivered": {
      -      "description": "TRUE only when QuickBooks recorded an actual delivery time. This — not emailStatus — is the delivery confirmation.",
      -      "type": "boolean"
      -    },
      -    "deliveryTime": {
      -      "description": "When QuickBooks delivered the document",
      -      "type": "string"
      -    },
      -    "documentId": {
      -      "type": "string"
      -    },
      -    "documentNumber": {
      -      "description": "DocNumber of the document that was sent",
      -      "type": "string"
      -    },
      -    "documentType": {
      -      "type": "string"
      -    },
      -    "email": {
      -      "description": "Address QuickBooks delivered to, and now the address stored on the document",
      -      "type": "string"
      -    },
      -    "emailStatus": {
      -      "type": "string"
      -    },
      -    "errorCode": {
      -      "description": "Machine-readable failure code (NO_EMAIL_ADDRESS, DOCUMENT_VOIDED, SEND_NOT_CONFIRMED, TYPE_MISMATCH, NOT_FOUND, INVALID_ID, TOKEN_EXPIRED, or a QuickBooks code such as 2380/2210). Branch on this instead of parsing the message.",
      -      "type": "string"
      -    },
      -    "message": {
      -      "type": "string"
      -    },
      -    "success": {
      -      "type": "boolean"
      -    },
      -    "totalAmount": {
      -      "type": "number"
      -    },
      -    "warning": {
      -      "description": "Present once after the active company was changed by something other than this connection (the portal, or another AI client). Confirm the company with the user before writing.",
      -      "type": "string"
      -    }
      -  },
      -  "required": [
      -    "success",
      -    "message"
      -  ],
      -  "type": "object"
      -}New value: +null
  2. Changed1 schema field changed
    • changedInput schema / properties / sendTo / pattern
      Previous value: -"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"New value: +"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
  3. Changed1 schema field changed
    • removedOutput schema / properties / company / properties / realmId
      Removed value: -{
      -  "description": "QuickBooks realm id, when connected.",
      -  "type": "string"
      -}
  4. Changed3 schema fields changed
    • changedInput schema / properties / documentId / description
      Previous value: -"QuickBooks id of the document — the NUMERIC id from qbFetchTransactions (or qbEstimate), not the document number. An id belongs to one type only, so it must match documentType."New value: +"The NUMERIC id (qbFetchTransactions), not the document number; it must be of documentType."
    • changedInput schema / properties / documentType / description
      Previous value: -"The kind of document to email. Only sales documents can be emailed — purchase-side records (Bill, Expense/Purchase, VendorCredit, BillPayment) have no send endpoint in QuickBooks because they are internal records, not documents you send a customer."New value: +"Sales document type (purchase records cannot be emailed)."
    • changedInput schema / properties / sendTo / description
      Previous value: -"Deliver to this address instead of the one stored on the document. WARNING: QuickBooks does not treat this as a one-off redirect — it OVERWRITES the document's stored BillEmail, so every later send goes here too. Omit it to use the address already on the document."New value: +"Deliver here instead of the stored address. It permanently OVERWRITES the document's stored address, so later sends go here too. Omit to use the stored one."
  5. First observed

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and openWorldHint=true, and the description still adds material behavior: the email is irreversible, a confirm:true gate applies unless the host app prompts the user, delivery is only real when delivered:true with deliveryTime, and voided documents or missing addresses are refused. That is unusually complete disclosure of side effects and failure modes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the identity of the tool and the irreversibility warning before mechanics, with no filler sentences. The telegraphic phrasing ('Delivered only when delivered:true') is dense but readable; a slightly cleaner separation of the confirm gate would improve flow.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, externally visible write with no output schema, the definition covers the confirmation protocol, irreversibility, success criteria, and refusal conditions. An agent has everything needed to call it safely without guessing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 60% and the description fills the important gaps by flagging documentType/documentId as required and explaining what confirm means in practice. The sendTo overwrite semantics come from the schema rather than the description, so it adds meaning without fully carrying parameter documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb (email) and precise resource (QuickBooks sales documents), and enumerates the five supported document types. It also explicitly separates itself from recording tools, so an agent can pick it without inspecting schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States when this tool is the right choice ('The ONLY tool that emails a customer') and pre-empts the classic mis-selection by explaining that recording never sends and that emailStatus 'NeedToSend' only queues for a human. It also gives explicit negative guidance: never send to test, never re-send to be sure.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.