SideQuest live in 30 minutes.
Five steps. The longest part is the QuickBooks OAuth setup. After that, you process POs by asking Claude Desktop to do it.
sidequest. Anywhere you see sidequest doctor, sidequest dashboard, sidequest reauth-qb etc., that's the canonical name to use. If you installed before v0.15.15 you may also see qb-distributor-mcp in older docs or in your claude_desktop_config.json — that's the legacy alias and it still works on every install. The on-disk directory at ~/.qb-distributor-mcp/ is the install location and that path has not changed.
Pick your computer. The steps below switch instantly.
Step 0 · Check your email host (30 seconds)
SideQuest reads inbound POs from Gmail natively. Other hosts work via a 10-minute forwarding setup. Type your domain or email address and we'll check the MX records and tell you which path applies.
Step 1 · Install the connector (5 min)
Unzip the connector folder from your welcome email. It goes somewhere like ~/Downloads/sidequest-connector.
Open Terminal (Command+Space → "Terminal" → Return). Type cd (with a trailing space), drag the sidequest-connector folder from Finder into the Terminal window, press Return. Run:
bash install-connector.sh
Find sidequest-connector.zip in your Downloads folder. Right-click it and pick Extract All.
Open the unzipped sidequest-connector folder in File Explorer. Double-click install.bat. A PowerShell window opens and runs the installer. If Windows SmartScreen warns you, click More info → Run anyway.
If the installer says Python is missing, install Python 3.12 from python.org first. Check the "Add python.exe to PATH" box on the first installer screen. Then double-click install.bat again.
About 60 seconds in, the installer pauses and asks for your license key. Copy it from your welcome email, paste it in when prompted, press ReturnEnter. The installer saves the key.
When it finishes you see All done and your tier (Free, Solo, Growth, or Scale). The installer adds sidequest to your PATH (the legacy name qb-distributor-mcp is still aliased for installs from before v0.15.15).
Step 2 · Connect QuickBooks via our hosted helper page (3 min)
Fastest path: use the hosted helper at sidequestautomation.com/qb/start. It removes most of the OAuth Playground tangent: paste your Client ID, click one button, sign in to QuickBooks, copy two values back to your terminal. If you'd rather see the underlying Playground flow,If you'd rather see the underlying Playground flow, the steps still work; expand the details below.
2a · Create the Intuit Developer app
- Open developer.intuit.com/app/developer/myapps. Sign in with your QuickBooks login.
- Click Create app → QuickBooks Online and Payments. Name it whatever you want (e.g. SideQuest).
- Open Keys & OAuth → Production (or Development if you're testing). Under Redirect URIs, click Add URI and paste exactly:
https://sidequestautomation.com/qb/callback. Save. - Copy two values from this page: Client ID and Client Secret. Save them in a temporary text file.
2b · Run the hosted authorization helper
- Open sidequestautomation.com/qb/start.
- Paste your Client ID from step 2a into the field. Pick Sandbox or Production.
- Click Authorize QuickBooks. Intuit opens in a new tab. Sign in, pick the QB company, click Connect.
- Intuit redirects you to sidequestautomation.com/qb/callback which shows your authorization code and realm ID in two copy-paste boxes.
Prefer the old OAuth Playground flow? Expand here.
- Open developer.intuit.com/app/developer/playground.
- Select your workspace, then your SideQuest app.
- Check the
com.intuit.quickbooks.accountingscope. - Click Get authorization code. Click Connect on the consent screen.
- Back on the Playground, click Get tokens.
- Copy Refresh token (starts with
RT1-) and Realm ID from the page.
2c · Write the values into .env
In TerminalPowerShell, paste this block. Replace each YOUR_... with the values from 2b, then press ReturnEnter.
cat > ~/.qb-distributor-mcp/.env <<EOF
QB_CLIENT_ID=YOUR_CLIENT_ID
QB_CLIENT_SECRET=YOUR_CLIENT_SECRET
QB_REALM_ID=YOUR_REALM_ID
QB_REFRESH_TOKEN=YOUR_REFRESH_TOKEN
QB_ENVIRONMENT=sandbox
QB_REDIRECT_URI=http://localhost:8765/callback
GMAIL_PO_LABEL=purchase-orders
EOF
@"
QB_CLIENT_ID=YOUR_CLIENT_ID
QB_CLIENT_SECRET=YOUR_CLIENT_SECRET
QB_REALM_ID=YOUR_REALM_ID
QB_REFRESH_TOKEN=YOUR_REFRESH_TOKEN
QB_ENVIRONMENT=sandbox
QB_REDIRECT_URI=http://localhost:8765/callback
GMAIL_PO_LABEL=purchase-orders
"@ | Set-Content -Path "$HOME\.qb-distributor-mcp\.env"
Step 3 · Connect Gmail via Google Cloud Console (10 min)
3a · Create a Google Cloud project
- Open console.cloud.google.com signed in as the Gmail account that receives your POs.
- Accept Google Cloud's Terms of Service if first time.
- Create project → name it
SideQuest Automation. Wait for it to provision.
3b · Enable the Gmail API
- Open the Gmail API library page. Confirm the project picker at top shows SideQuest Automation.
- Click Enable.
3c · Configure the OAuth consent screen
- Open OAuth Overview → click Get started.
- App name: SideQuest Automation. Support email: your Gmail.
- Audience: External. (Internal is only for Google Workspace orgs.)
- Contact email: your Gmail. Agree to the Google API User Data Policy. Create.
3d · Add yourself as a test user
Required. Without this, the OAuth dance fails with access_denied.
- Click Audience in the left nav.
- Scroll to Test users → + Add users.
- Type your Gmail address, press Return, click Save.
3e · Create the Desktop OAuth client
- Click Clients in the left nav → Create client.
- Application type: Desktop app. Name: SideQuest Connector. Click Create.
3f · Get the complete client_secret JSON
Google's rules changed in June 2025. Client secrets are now only visible at the moment the OAuth client is created. After you close the create dialog, the secret is masked everywhere in the Cloud Console and the only way to get a working client_secret.json is to add a new secret to the same client.
If you just created the client and the "Download JSON" button was offered to you, click it now — that file has the full secret. If you missed it (or you're using an older client where the first download wasn't usable), do this instead:
- On the Clients list, click on SideQuest Connector to open the detail page.
- Scroll to Client secrets. Click + Add secret. A new row appears with a NEW badge.
- Click the download icon next to the NEW secret immediately, before you navigate away. The file Google saves now has the complete
"client_secret": "GOCSPX-..."inside. Google's announcement: developers.googleblog.com.
Move the file into the connector folder:
mv ~/Downloads/client_secret_2_*.apps.googleusercontent.com.json \
~/.qb-distributor-mcp/google_client_secret.json
Move-Item "$HOME\Downloads\client_secret_2_*.apps.googleusercontent.com.json" `
"$HOME\.qb-distributor-mcp\google_client_secret.json"
Verify the file has the secret (Mac):
grep client_secret ~/.qb-distributor-mcp/google_client_secret.jsonSelect-String -Path "$HOME\.qb-distributor-mcp\google_client_secret.json" -Pattern "client_secret"You should see "client_secret":"GOCSPX-...". If you see nothing, you grabbed the incomplete first download. Repeat 3f.
3g · Add Gmail paths to .env
printf "\nGOOGLE_CLIENT_SECRETS_PATH=$HOME/.qb-distributor-mcp/google_client_secret.json\nGOOGLE_TOKEN_PATH=$HOME/.qb-distributor-mcp/google_token.json\n" >> ~/.qb-distributor-mcp/.env
Add-Content -Path "$HOME\.qb-distributor-mcp\.env" -Value @"
GOOGLE_CLIENT_SECRETS_PATH=$HOME\.qb-distributor-mcp\google_client_secret.json
GOOGLE_TOKEN_PATH=$HOME\.qb-distributor-mcp\google_token.json
"@
3h · Run the Gmail OAuth dance
~/.qb-distributor-mcp/venv/bin/python -c "
from pathlib import Path
from qb_distributor_mcp.gmail_client import GmailClient
home = Path.home() / '.qb-distributor-mcp'
client = GmailClient(home / 'google_client_secret.json', home / 'google_token.json')
print('Token file:', (home / 'google_token.json').exists())
"
& "$HOME\.qb-distributor-mcp\venv\Scripts\python.exe" -c "from pathlib import Path; from qb_distributor_mcp.gmail_client import GmailClient; home = Path.home() / '.qb-distributor-mcp'; client = GmailClient(home / 'google_client_secret.json', home / 'google_token.json'); print('Token file:', (home / 'google_token.json').exists())"
A browser tab opens. Click your Gmail account. You will see "Google hasn't verified this app." That is normal — your app is in Testing mode because you just created it. Click Advanced (small link, bottom-left), then Go to SideQuest Automation (unsafe), then Continue to grant Gmail read/modify access.
Browser says "The authentication flow has completed." Terminal prints Token file: True.
Step 4 · Wire credentials into Claude Desktop (2 min)
The MCP server Claude Desktop launches does not read ~/.qb-distributor-mcp/.env. It runs from a different working directory, so the env file is invisible to it. The fix is to copy every value from your .env into Claude Desktop's claude_desktop_config.json under the env block.
The installer ships a one-command reinject script for this. Run it from any Terminal:
~/.qb-distributor-mcp/venv/bin/python ~/.qb-distributor-mcp/reinject.py
& "$HOME\.qb-distributor-mcp\venv\Scripts\python.exe" "$HOME\.qb-distributor-mcp\reinject.py"
The script reads .env, writes the env block to Claude Desktop's config under the sidequest-automation server key (auto-migrating the older qb-distributor key if present), and prints how many vars it injected with secrets masked. You should see at least 9 vars. If the count is lower, your .env is missing one of the QB or Gmail entries from Steps 2 and 3.
Now fully quit Claude Desktop. Use Claude → Quit Claude or Cmd+Q. Closing the window is not enough.Right-click the Claude icon in the system tray (bottom-right, near the clock) and pick Quit. Closing the window is not enough. Reopen Claude Desktop. You should see SideQuest Automation in the MCP tool list.
Step 5 · Process a test PO (3 min)
v0.15.9 update: You no longer need to create a Gmail label or filter as setup. The connector scans your inbox for POs automatically — subject keywords (PO, purchase order, order #), PDF attachments, body anchors — and auto-applies the purchase-orders label to anything it finds. The label gets created in Gmail on first use.
Forward a real PO email to yourself (or compose a fake one with subject "PO #1234" and any line items in the body). Then open Claude Desktop and ask:
List my incoming purchase orders and draft an estimate for each one.
If you want to scope SideQuest to ONLY POs from specific customers (rather than auto-detecting from the whole inbox), you can still create a Gmail filter to apply purchase-orders only on those sender domains. Optional, not required.
Claude reads the labeled email, parses the PO, matches every line against your QuickBooks catalog, flags pricing variances, and shows you the draft inline in chat. Each draft has a review_url like qbd://drafts/abc123 you can reference in follow-up messages.
To edit, say things like:
- "Change line 2 quantity to 10."
- "Replace the SKU on line 3 with BR-ELB-050-NPT."
- "Apply a 5% discount to the whole draft."
When it looks right, ask Claude to submit:
Submit draft abc123 to QuickBooks.
The Estimate writes to QuickBooks Online. Claude replies with the QB Estimate number and a link to open it in QuickBooks.
Step 6 · Turn on the auto-learn flywheel
SideQuest matches part numbers with exact-SKU lookup, then cross-references, then fuzzy matching. The middle layer — your cross-reference table — is where customer-specific aliases live. Day one with no table: ~85% match rate. Day one with a seeded table: ~99%. Even better, every time you manually fix an unmatched line via Claude Desktop, that fix gets written to the table automatically, so the table grows itself.
Two ways to seed it. Either (a) create an empty file now and let auto-learn populate it as operators work, or (b) bulk-load your existing customer aliases into the file up front. Either way you need the env var set and the file path created.
Create the file in any text editor:
touch ~/.qb-distributor-mcp/cross_reference.csv
open -a TextEdit ~/.qb-distributor-mcp/cross_reference.csv
If TextEdit opens in Rich Text, switch to plain via Format → Make Plain Text.
Press Win+R, paste this path, press Enter to open the folder:
%USERPROFILE%\.qb-distributor-mcp
Right-click in the folder, pick New → Text Document, name it cross_reference.csv (make sure Windows doesn't add a .txt on the end — turn on "File name extensions" in File Explorer's View menu if you can't tell). Open it in Notepad.
Add rows in this format:
customer_id,customer_part,internal_sku,notes
ACME,ACME-EL34,BR-ELB-075-NPT,Acme's catalog code for 3/4" brass elbow
ACME,ACME-EL12,BR-ELB-050-NPT,
,LEGACY-12NPT,BR-ELB-050-NPT,Global alias works for any customer
,COMPETITOR-X1,FS-BOLT-25-100,Picked up from competitor pricing
Leave customer_id blank for global aliases. The matcher prefers a customer-specific row when both exist. Save. Add this line by hand to ~/.qb-distributor-mcp/.env:
CROSS_REFERENCE_CSV=/Users/YOU/.qb-distributor-mcp/cross_reference.csvCROSS_REFERENCE_CSV=C:\Users\YOU\.qb-distributor-mcp\cross_reference.csvRerun the Step 4 reinject so the new CROSS_REFERENCE_CSV value lands in Claude Desktop's config too. Cmd+Q Claude Desktop, reopen. The next PO uses your new mappings.
You're done
That's the whole loop. From now on:
- Open Claude Desktop.
- Ask "list my incoming purchase orders and draft estimates."
- Review the drafts, edit by chat, ask Claude to submit.
- The Estimate lands in QuickBooks Online.
One-shot morning routine (v0.15.5+)
Once you're past Day 1, the morning routine collapses to a single sentence:
Process the overnight queue.
SideQuest's process_overnight_queue() runs an auto-label preflight first (so any PO that arrived overnight without your purchase-orders label still gets picked up), then parses, matches, and drafts every unread PO in one server-side loop. Returns three buckets: auto_clean, needs_review, failed_to_parse. Follow with "preview the clean ones" and "submit them" to send everything that passed validation to QuickBooks.
SideQuest also skips emails you sent from your own watched Gmail (v0.15.6 self-sent filter), and any line that matched a catalog item on description alone — no part number — is always flagged for review before it can be submitted.
When you're ready for production, edit ~/.qb-distributor-mcp/.env and change QB_ENVIRONMENT=sandbox to QB_ENVIRONMENT=production. Then run sidequest reauth-qb from any Terminal — it walks the Intuit OAuth dance against your real QB company, writes the new QB_REALM_ID and QB_REFRESH_TOKEN to .env, and auto-reinjects into Claude Desktop's config. Cmd+Q Claude Desktop and reopen.
From v0.15.13 onward the refresh token rotates itself on every refresh and gets persisted back to .env automatically, with cross-process file locking. You only need to run sidequest reauth-qb at the initial seed and if you ever revoke the grant in QuickBooks.
Verify your setup any time
Run the diagnostic check:
sidequest doctor
It prints your license tier, QB realm ID, Gmail account, runs a sample call against the demo catalog, and exercises the QB refresh-token chain end to end. If the token chain is dead it shows a "QuickBooks token needs reseeding" banner with the exact reseed command. Secrets are redacted, so it's safe to paste into a support email.
Troubleshooting common Day-1 issues
"Claude Desktop doesn't show 'sidequest-automation' in the MCP list"
Four things to check.
(1) The config file path is correct. ~/Library/Application Support/Claude/claude_desktop_config.json (note the spaces).Direct .exe install: %APPDATA%\Claude\claude_desktop_config.json. Microsoft Store install: %LOCALAPPDATA%\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\claude_desktop_config.json — v0.15.7+ reinject.py writes to BOTH automatically. If you're on v0.15.6 or earlier on a Store install, the MCP will silently fail to load. Re-run the installer to pick up v0.15.7.
(2) The JSON parses cleanly. Paste it into any JSON validator online to confirm.
(3) The command path inside the config points to the right binary. Mac: ends in venv/bin/sidequest (or venv/bin/qb-distributor-mcp on installs from before v0.15.15 — the legacy alias still works).Windows: ends in venv\Scripts\sidequest.exe — note the .exe suffix and the Scripts (not bin) folder. Pre-v0.15.7 reinject.py used the Unix path on Windows; if that's what's in your config, re-run reinject.py from v0.15.7+.
(4) You restarted Claude Desktop fully. Cmd+Q to quit, then reopen — closing the window isn't enough.Right-click the Claude icon in the system tray and pick Quit, then reopen — closing the window isn't enough.
"Claude says 'no incoming POs found' but I labeled one"
Two checks. (1) Open the message in Gmail and confirm the label chip shows next to the subject. (2) The label name in ~/.qb-distributor-mcp/.env (GMAIL_PO_LABEL=) matches exactly what you used in Gmail — case-sensitive, hyphens count. If you change one, change the other and restart Claude Desktop.
"Match confidence is low on every line"
Your cross-reference table is probably empty or undersized. Open ~/.qb-distributor-mcp/cross_reference.csv and check the row count. Most distributors need at least 100 mappings before match quality stabilizes. Email [email protected] with a CSV of your customer's past POs and we'll help you extract the cross-references in batch.
"QuickBooks returns an error when Claude tries to submit"
Usually an OAuth permissions issue. Run sidequest reauth-qb from any Terminal. It walks the Intuit OAuth dance, mints a fresh refresh token, writes it to .env, and auto-pushes it into Claude Desktop's config in one shot. Then Cmd+Q Claude Desktop and reopen. If the error persists, check the operator runbook for QB-specific error codes (3200, 5010, etc.).
"Setup wizard hangs at 'Listening for redirect on localhost:8765'"
That is Intuit silently rejecting http://localhost:8765/callback as a redirect URI. The wizard cannot complete. Press Ctrl+C, skip the wizard for the QuickBooks step, and follow Step 2 above (OAuth Playground).
"Gmail OAuth fails with KeyError: 'client_secret'"
Your google_client_secret.json is the first download Google gave you, which is missing the secret. Open Google Cloud → Clients, open your OAuth client, click + Add secret, then download that second secret. Replace ~/.qb-distributor-mcp/google_client_secret.json with the new file and rerun the OAuth dance (Step 3h).
"Gmail OAuth returns access_denied"
Your app is in External + Testing mode and your Gmail address is not in the test users list. Go to Audience → Test users, click + Add users, type your Gmail, save. Then retry the Gmail OAuth dance.
"Claude says QB_REALM_ID and QB_REFRESH_TOKEN aren't set, but they're in my .env"
The MCP server Claude Desktop launches does not read ~/.qb-distributor-mcp/.env (it runs from a different working directory). Your env vars need to live inside the env block of claude_desktop_config.json too. Rerun the Step 4 reinject, then Cmd+Q Claude Desktop and reopen.
"sidequest doctor shows every env var as 'unset'"
Doctor reads os.environ, not your .env file or the Claude Desktop config. Only the live MCP server (started by Claude Desktop) loads those. Doctor's "unset" line is misleading, not broken. To verify the wiring, ask Claude Desktop a real question like list 5 items from my QuickBooks sandbox.
"sidequest doctor says 'license_not_found'"
The license key in your .env file doesn't match what's on the SideQuest control plane. Double-check the key against your welcome email. If you mistyped it during install, re-run the installer (bash install-connector.sh from the connector folderdouble-click install.bat in the connector folder). Answer n when it asks if you want to keep the existing key, then paste a fresh one.
"I want handwritten POs parsed automatically"
Optional. Open your .env file (~/.qb-distributor-mcp/.env%USERPROFILE%\.qb-distributor-mcp\.env) and add the line ANTHROPIC_API_KEY=sk-ant-.... The connector uses Claude vision to read handwriting. Cost is roughly $0.005-$0.01 per handwritten PO. Skip it and handwritten POs come back flagged for manual review.