Back to Blog

Use AI and Your Database for Customer Support Questions

Support shouldn't wait on engineering for 'when did they cancel?' Point Claude or ChatGPT at a safe read-only connection — prompts, table allowlists, and what never to put in a ticket reply.

Ticket: “I was charged after I cancelled.” Support needs one fact — when did status change? — and engineering is in a standup.

That’s a read. It shouldn’t need a deploy or a SQL expert every time. With read-only access in Claude or ChatGPT, support can ask in plain English — if the connection can’t wander into a full users dump.

Ops path. Not a replacement for your admin UI. Not a refund button in chat.

Also: replica, table allowlists, SELECT-only, where results go, team sharing.

What support should ask the database

Good (facts that exist as rows):

  • Subscription / plan status right now
  • cancelled_at / period end if you store them
  • Last login or last meaningful event (if logged)
  • Whether an order/id in the ticket exists
  • Count of open invoices for this account (if in DB)

Bad (wrong tool):

  • “Refund them” / any write
  • “Why are they upset?” with no reason field (churn post)
  • Dumping full message history or card data into chat

Actions stay in Stripe/admin. AI stays on SELECT.

Connection shape for support

| Setting | Recommendation | |---------|----------------| | Environment | Replica or fresh staging — not casual primary | | DB user | SELECT-only | | Tables | subscriptions, orders, events — not raw token tables | | Endpoint | Separate Synra connection: support-replica | | Who has the URL | Support leads first; rotate if it hits a public channel |

One shared immortal prod URL in #support is how you get a privacy incident. Share like team access.

Prompt: lookup by ticket email or id

Read-only. Inspect schema first.
Customer email or id from the ticket: <paste>

Find their account/subscription row(s).
Return only:
- internal id
- plan / status
- created_at, cancelled_at or current_period_end if present
- last_seen / last_login if present

Do not print password hashes, tokens, or full payment PANs.
Show SQL. If multiple accounts match, list them and stop.

Prompt: “charged after cancel”

Account id: <id>
Using subscriptions/invoices/charges tables we actually have,
list dates for: cancel or cancel_at_period_end, and any charge/invoice
after that date. Define columns from the schema — don't invent Stripe fields
if they're not synced here. Show SQL.

If billing truth lives only in Stripe, say so in the prompt. The model can’t see Stripe unless you synced it.

Prompt: rules for every support thread

For support lookups:
- SELECT only
- Prefer the id/email already in the ticket — don't browse random users
- Mask emails in the summary if not required in the reply
- If unsure, say UNSURE — never invent dates for the customer

Before you turn support loose

  1. Verify three lookups against the admin UI
  2. Deliberate write → must fail
  3. Confirm allowlist hides secrets
  4. One person owns Usage week one
  5. Written rule: “Never paste AI output to the customer without checking admin/Stripe”

When not to use this

  • You have no replica/staging and production is full of PII you won’t put in chat — build admin UI filters instead
  • The question needs a write (password reset, refund)
  • You’re fighting metric definitions (“active”) in a ticket — use BI/admin

When not to connect still applies.


Support needs facts; engineering needs focus. A tight read-only connector helps — if the endpoint and allowlist are serious.

Replica/staging: mcpserver.design (7-day Solo trial). Name it support-replica.

Related reading: