Operate a backend-free invoice agent in Claude Desktop using connector apps for Gmail/Slack/QBO/Sheets and local SQLite MCP for persistent state, audit logs, vendor master, and purchase orders.
Run this skill whenever executing the invoice workflow in Claude Desktop without a backend.
Treat end users as non-technical. Never require MCP/tool/database language in user prompts.
init_storage, seed_master_data, or other tool names.audit_logs.INGESTED — just pulled from email, not yet validatedFLAGGED — validation failed, needs human reviewREADY_FOR_APPROVAL — validation passed, awaiting approval decisionAPPROVED — explicitly approved by operator in chatREJECTED — explicitly rejected by operator in chatPOSTED — successfully sent to QBOPOST_FAILED — QBO post attempted but failedfinance_admin.INGESTED ──(validation pass)──► READY_FOR_APPROVAL ──(chat: approve)──► APPROVED ──(chat: post)──► POSTED
──(validation fail)──► FLAGGED ──(chat: reject)──► REJECTED
──(chat: approve flagged with note)──► APPROVED
APPROVED.POSTED or POST_FAILED.REJECTED.FLAGGED invoice can be approved with an explicit override note, but the note is mandatory.Claude is the extraction engine. There is no OCR service, no document intelligence pipeline, no regex parser. Claude reads whatever text the Gmail MCP returns and uses its own language understanding to extract structured fields.
When pulling invoices from Gmail:
gmail_read_message to get the full message including attachment metadata.invoice_number, vendor_name, po_number, subtotal, tax, total, due_date, bank_accountseed_data.json or the invoice manifest to fill invoice field values. That file is only used as the vendor master and PO register for cross-referencing — never as a source of invoice amounts, invoice numbers, or other per-invoice data.AMOUNT_UNCONFIRMED if subtotal/tax/total could not be verifiednotes: "PDF not accessible via connector — fields extracted from email body/subject/filename only"AMOUNT_MISMATCH if exceeded.BANK_ACCOUNT_CHANGED.UNKNOWN_VENDOR if vendor not in master.PO_NOT_FOUND if PO missing or unmatched.DUPLICATE if same invoice number already exists in storage for the same vendor.SUSPICIOUS_PATTERN for: single round-amount line, no line-item detail, "due on receipt" with unknown vendor, or urgency pressure language.FLAGGED. No flags → status READY_FOR_APPROVAL.When prompted send slack alert of invoice #X or notify team about invoice #X:
#finance, #ap, #invoices, or ask user once and remember).If status is FLAGGED with flag BANK_ACCOUNT_CHANGED:
🚨 *Invoice Flagged — Manual Review Required*
*Invoice #:* <invoice_number>
*Vendor:* <vendor_name>
*PO #:* <po_number>
*Amount:* $<total> (USD)
*Status:* FLAGGED 🔴
*Reason:* Bank account on invoice does not match vendor master on file (****<last4_of_master_account>). This may indicate a fraudulent bank change request. Please verify directly with <vendor_name> before approving payment. Do *not* process until confirmed.
_Sent using Claude_
If status is FLAGGED with any other flag:
🚨 *Invoice Flagged — Manual Review Required*
*Invoice #:* <invoice_number>
*Vendor:* <vendor_name>
*PO #:* <po_number>
*Amount:* $<total> (USD)
*Status:* FLAGGED 🔴
*Reason:* <human-readable explanation of the flag(s)>
To approve: reply in this channel with: approve invoice <id>
To reject: reply in this channel with: reject invoice <id> — <reason>
_Sent using Claude_
For all other statuses (READY_FOR_APPROVAL, APPROVED, etc.):
*Invoice Alert — Action Required*
*Invoice #:* <invoice_number>
*Vendor:* <vendor_name>
*PO #:* <po_number>
*Amount:* $<total> (USD)
*Status:* <status>
*Flags:* <flags or "None">
To approve: reply in this channel with: approve invoice <id>
To reject: reply in this channel with: reject invoice <id> — <reason>
Then confirm your decision back in Claude to update the record.
SLACK_ALERT_SENT.When prompted send email alert of invoice #X, email the team about invoice #X, or send alert of invoice #X to mail:
to field blank in the draft — do not set any default recipient. The user will fill it in before sending.gmail_create_draft (not send) to create the email draft. Confirm draft creation to the user with a link.If status is FLAGGED with flag BANK_ACCOUNT_CHANGED:
Subject: URGENT: Invoice Flagged - Bank Account Change Detected | <vendor_name> | <invoice_number>
Body:
Hi,
This is an automated alert from the Invoice Processing System.
⚠️ ACTION REQUIRED — Invoice has been flagged and requires manual verification before approval.
Invoice Details:
- Invoice #: <invoice_number>
- Vendor: <vendor_name>
- PO #: <po_number>
- Amount: $<total> (USD)
- Status: FLAGGED
Reason for Flag:
The bank account on this invoice does not match the vendor master on file (master: ****<last4_of_master_account>). This may indicate a fraudulent bank change request (Business Email Compromise / BEC).
Required Action:
Please verify the bank account change directly with <vendor_name> via a known, trusted contact before approving payment. Do NOT process this invoice until the change has been confirmed.
Do not reply to any email from the vendor requesting this change without independent verification.
Regards,
Invoice Processing System
If status is FLAGGED with any other flag:
Subject: URGENT: Invoice Flagged - Action Required | <vendor_name> | <invoice_number>
Body:
Hi,
This is an automated alert from the Invoice Processing System.
⚠️ ACTION REQUIRED — Invoice has been flagged and requires manual verification before approval.
Invoice Details:
- Invoice #: <invoice_number>
- Vendor: <vendor_name>
- PO #: <po_number>
- Amount: $<total> (USD)
- Status: FLAGGED
Reason for Flag:
<human-readable explanation of the flag(s)>
Required Action:
Please review this invoice carefully before approving payment.
To approve: reply to this email with: approve invoice <id>
To reject: reply to this email with: reject invoice <id> — <reason>
Then confirm your decision in Claude to update the record.
Regards,
Invoice Processing System
For all other statuses (READY_FOR_APPROVAL, APPROVED, etc.):
Subject: Invoice Alert: <invoice_number> from <vendor_name> — <status>
Body:
Hi,
The following invoice requires your review:
Invoice #: <invoice_number>
Vendor: <vendor_name>
Amount: $<total> (USD)
PO: <po_number>
Status: <status>
Flags: <flags or "None">
To approve: reply to this email with: approve invoice <id>
To reject: reply to this email with: reject invoice <id> — <reason>
Then confirm your decision in Claude to update the record.
Regards,
Invoice Processing System
EMAIL_DRAFT_CREATED.When operator says approve invoice #X (optionally with a note):
FLAGGED, a note is mandatory — ask for it if not provided.APPROVED.APPROVED, actor finance_admin, details include note if provided.When operator says reject invoice #X with a reason:
REJECTED.REJECTED, actor finance_admin, details include reason.When operator says post invoice #X to QBO or post approved invoices to accounting:
APPROVED.POSTED, log POSTED to audit_logs.POST_FAILED, log POST_FAILED with error details.When prompted create month-end report, share month-end summary, post month-end report, or similar:
get_report_summary for the current month/year and list_invoices to gather all data.gmail_send_email. The recipient must be the same Gmail address connected for invoice ingestion — identify this by calling gmail_get_profile to retrieve the authenticated user's email address. Never leave the to field blank for month-end reports.MONTH_END_REPORT_SHARED, including Slack link and email confirmation.Email template:
Subject: Invoice Processing Report — <YYYY-MM>
Body:
Hi,
Please find below the month-end invoice processing report.
SUMMARY
- Report Date: <today>
- Period: <YYYY-MM>
- Total Invoices Processed: <count>
- Total Payables: $<total>
- Posted to QBO: $<posted_total>
- Pending Review (Flagged): $<flagged_total>
- Approved (not yet posted): $<approved_total>
- Rejected: $<rejected_total>
STATUS BREAKDOWN
- POSTED: <count> invoice(s) — $<amount>
- FLAGGED: <count> invoice(s) — $<amount>
- APPROVED: <count> invoice(s) — $<amount>
- REJECTED: <count> invoice(s) — $<amount>
INVOICE DETAIL
<for each invoice: invoice_number | vendor_name | $total | status | flags>
KEY OBSERVATIONS
<numbered list of notable items>
Regards,
Invoice Processing System
| What user says | What to do |
|---|---|
Start my invoice workspace for today | init_storage + seed master data if missing, confirm ready |
Load my vendor and PO records | seed/refresh vendor + PO master tables |
Get latest invoices from mail / Ingest from mail | Pull Gmail, extract fields from body + attachment metadata, validate, persist |
Show invoices waiting for review | List FLAGGED + READY_FOR_APPROVAL in a table |
Approve invoice <id> | Transition to APPROVED, write audit |
Reject invoice <id> with note ... | Transition to REJECTED, write audit |
Post invoice <id> to QBO / Post approved invoices | Post to QBO, mark POSTED or POST_FAILED |
Send slack alert of invoice <id> | Send Slack message with invoice details + approve/reject instructions |
Send email alert of invoice <id> | Send email with invoice details + approve/reject instructions |
Share month-end summary / Create month-end report | Compute report, send Slack message + send email (not draft) to ingesting Gmail, log audit |
init_storageseed_master_dataupsert_invoicelist_invoicestransition_invoice_statusadd_audit_logget_report_summaryreferences/workflow.mdreferences/prompt-pack.mdreferences/integration-setup.md