Claude.ai's MCP auth callback requires a state parameter. Generate a random
state in /oauth/connect-claude-ai and preserve it through the consent form
and login redirect so it is echoed back to claude.ai.
Add https://claude.ai/api/mcp/auth_callback to the pre-registered OAuth
client redirect_uris so the new /oauth/connect-claude-ai route works.
ensureOAuthAppRegistered uses ON DUPLICATE KEY UPDATE so the DB row is
updated on the next server startup.
- Replace single 'Connect to Claude / ChatGPT' button with a modal picker
offering Claude.ai web, Claude Desktop, Codex CLI, and ChatGPT/GPT Actions.
- Add /oauth/connect-claude-ai backend route that redirects to Anthropic's
official https://claude.ai/api/mcp/auth_callback OAuth callback.
- Update MCP callback result page with browser-specific instructions for
Claude.ai web, Claude Desktop, ChatGPT/GPT Actions, and Codex CLI.
- Deploy new app and hermes images to K8s.
The global express.json() middleware at line 77 was parsing the body
into a JS object before the route-level express.raw() could capture
the raw Buffer. When WHATSAPP_APP_SECRET is set and a signature is
present, crypto.createHmac().update(req.body) received an Object
instead of Buffer, throwing TypeError and crashing the process.
Fix: register app.use('/webhook/whatsapp', express.raw({ type: '*/*' }))
before app.use(express.json()) so the raw body is preserved for HMAC.
Post-deploy verification: all 7 webhook tests pass, pod 0 restarts.
Related: SquareMCP/2026-06-10-twilio-whatsapp-webhook-deployment.md
Replaces direct Poste.io SMTP (mail.squaremcp.com:30587, port 25 blocked)
with Azure Communication Services relay (smtp.azurecomm.net:587).
All sqcp_* accounts share a single ACS credential; FROM addresses unchanged.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- CRITICAL: forgot-password no longer returns token in response; sends email via info@squaremcp.com instead
- Rate limit: login 10/15min, forgot-password 5/hr, chat 30/hr (Redis, per IP)
- express.json() capped at 100kb
- WhatsApp webhook HMAC verification (activates when WHATSAPP_APP_SECRET is set)
- JWT_SECRET now explicitly set in K8s (was falling back to CREDENTIAL_ENCRYPTION_KEY)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Customers who haven't connected WhatsApp in the dashboard now
automatically use the SquareMCP default number (+19547385805 via Twilio)
instead of throwing 'WhatsApp not connected'. Routing flag usingDefault
replaces the !customer check so OAuth sessions get the same Twilio path.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ChatGPT regenerates its GPT ID (and callback URL) every time the GPT
is saved, making exact redirect_uri matching impossible. Added support
for the registered URI pattern https://chat.openai.com/aip/*/oauth/callback
which matches any valid ChatGPT GPT callback via regex.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Drops obsidian (5 ops) and whatsapp/templates list (1 op) to stay
under ChatGPT's 30-operation cap. Served at /openapi-chatgpt.json.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The SquareMCP number (+19547385805) is registered under Twilio's BSP,
so direct Meta API sends were blocked with #200 permission errors.
Default account now routes through Twilio's REST API; customer-owned
accounts still use Meta's Cloud API directly.
- twilioSend(): POST to api.twilio.com with Basic auth
- resolveTemplateText(): fetches template body from Meta, substitutes
{{1}}/{{}} parameters, so templates render correctly via Twilio
- Bumped WHATSAPP_API_VERSION to v21.0
- Added TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_WHATSAPP_NUMBER,
WHATSAPP_DEFAULT_BUSINESS_ACCOUNT_ID to K8s deployment
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
WHATSAPP_DEFAULT_PHONE_NUMBER_ID, WHATSAPP_DEFAULT_ACCESS_TOKEN,
and WA_VERIFY_TOKEN (hermes-wa-2026) added to K8s deployment.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
POST /webhook/twilio/voice returns TwiML that says the number doesn't
accept voice calls and hangs up — needed for Twilio number config.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- notifications/slack.ts: added sendChatEscalationAlert (fires when visitor
asks about pricing, demo, help, or a human) and sendSupportEmailAlert
- email-poller.ts: polls support@squaremcp.com every 5 min via IMAP,
deduplicates with Redis (support📧alerted_uids), fires Slack alert
for each new unseen message
- index.ts: detectEscalation() scans last user message for trigger phrases;
chat endpoint fires alert fire-and-forget after responding; startEmailPoller()
called on server boot
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- chat.ts: system prompt now includes step-by-step ChatGPT Custom GPT
setup (openapi.json import + OAuth), Claude/Cursor/Windsurf config,
and mortgage broker guidance — bot no longer incorrectly says ChatGPT
is unsupported
- smtp.ts: all sqcp_* accounts now route to mail.squaremcp.com (SQCP_SMTP_HOST)
instead of the fetcherpay server
- tools.ts: ACCOUNT_PARAM description now lists all 14 mailboxes including
the 7 squaremcp.com accounts so Claude picks the right one without guessing
- package.json: postinstall hook runs imapflow patch script after npm install
- hermes-k8s.yaml: updated image digest to current production build
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New accounts: sqcp_garfield, sqcp_info, sqcp_sales, sqcp_support,
sqcp_founder, sqcp_contact, sqcp_admin
- All use same poste.io mail server as fetcherpay.com (IMAP 30993, SMTP 30587)
- Password: onelove for all accounts
- Updated: imap.ts, smtp.ts, tools.ts, manifest.ts, hermes-k8s.yaml