Build Deal-to-Invoice Automation with MCP and the SDK

Build automatic invoice generation from closed deals using MCP or the Python SDK.

Author

Haegwan Kim

Haegwan Kim - Founder & CEO at Sanka

Updated

April 6, 2026

Published: April 5, 2026

Build Deal-to-Invoice Automation with MCP and the SDK

A closed deal sits in your CRM for days before finance creates an invoice. The rep forgot to notify them. Or finance missed the Slack message. According to Nidish's 2026 RevOps audit, the integration between sales and finance is where the most "expensive" leakage occurs—billing errors, missed renewals, and simple timing delays that compound into cash flow problems.

If you just need the workflow without writing code, see the operator guide.

Deals pipeline showing closed-won deals ready for invoicing

What you'll build

  1. Query deals that closed but have no linked invoice
  2. Pull contact and billing details for each deal
  3. Create an invoice with correct line items
  4. Mark the deal as invoiced to prevent duplicates

Total setup time: 5 min with MCP, 15 min with the SDK.

Option A: Run it from Codex, Cursor, or Claude with MCP (5 min)

For developers who want AI to handle the orchestration. You describe the logic; the agent executes it.

Here's what it looks like in action:

Demo: Creating invoices from closed deals with MCP

1. Connect Sanka MCP

Add this to your MCP config:

JSON
{
  "mcpServers": {
    "sanka": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://mcp.sanka.com/mcp",
        "--resource",
        "https://mcp.sanka.com/mcp"
      ]
    }
  }
}

2. Describe what you want

Text
Find all deals with status "closed-won" that were updated in the last 7 days.
For each deal that doesn't have a linked invoice:
1. Get the associated contact's billing address
2. Create an invoice with the deal amount as a single line item
3. Link the invoice to the deal
4. Update the deal to mark it as invoiced

Show me what you're about to create before executing.

3. See the results

The agent will:

  • List deals missing invoices
  • Show the invoice payload for each
  • Wait for your confirmation
  • Execute the creates and updates
  • Report success or errors

You stay in control. The agent handles the API calls.

Deal detail showing amount and contact info


Option B: Build it with the SDK (15 min)

For production scripts, scheduled jobs, or when you need version control.

1. Install the SDK

Bash
pip install sanka-sdk

2. Build it

Python
from sanka_sdk import Sanka
from datetime import datetime, timedelta

client = Sanka(api_key="sk_live_...")

# Find closed deals from the last 7 days
seven_days_ago = (datetime.now() - timedelta(days=7)).isoformat()
deals = client.deals.list(
    filters={
        "status": "closed-won",
        "updated_at": {"gte": seven_days_ago}
    }
)

for deal in deals.data:
    # Check if invoice already exists
    existing_invoices = client.invoices.list(
        filters={"deal_id": deal.id}
    )

    if existing_invoices.data:
        print(f"Deal {deal.id} already has invoice, skipping")
        continue

    # Get contact for billing info
    contact = client.contacts.get(deal.contact_id)

    # Create invoice
    invoice = client.invoices.create({
        "contact_id": contact.id,
        "deal_id": deal.id,
        "due_date": (datetime.now() + timedelta(days=30)).isoformat(),
        "line_items": [
            {
                "description": deal.name,
                "quantity": 1,
                "unit_price": deal.amount
            }
        ],
        "billing_address": contact.billing_address,
        "status": "draft"
    })

    # Update deal to mark as invoiced
    client.deals.update(deal.id, {
        "custom_fields": {
            "invoiced": True,
            "invoice_id": invoice.id
        }
    })

    print(f"Created invoice {invoice.id} for deal {deal.name}")

3. Automate it

Run this as a daily cron job or trigger it via webhook when a deal status changes:

Python
# Webhook handler example (Flask)
@app.route("/webhooks/deal-closed", methods=["POST"])
def handle_deal_closed():
    payload = request.json
    deal_id = payload["deal_id"]

    # Same logic as above, but for a single deal
    deal = client.deals.get(deal_id)
    if deal.status == "closed-won":
        create_invoice_for_deal(deal)

    return {"status": "ok"}

Invoice created from deal


Example engineering scorecard

Use these KPIs as a rollout template. The 4.2-day handoff baseline comes from Scratchpad's 2023 RevOps Trends Report; replace the other baseline values with your team's actual pre-automation numbers.

MetricBeforeAfter
Average invoice delay4.2 daysSame-day
Manual invoice creation100%0% (auto-draft)
Duplicate invoice errors3/month0

Working remotely from Tokyo while supporting teams across regions has made timezone-safe automation feel less like a convenience and more like a requirement. When a deal closes at 5 PM in New York, the invoice shouldn't wait until someone in Tokyo wakes up to create it.

Next steps

Start by connecting MCP and asking: "Which closed deals are missing invoices?"

Related content

Author

Haegwan Kim

Haegwan Kim - Founder & CEO at Sanka

Helped 1000+ companies grow over 15 years through consulting services and SaaS. Father of two daughters, living in Tokyo.

Back to blog