Garfield 61dab40585 feat(saas): SquareMCP v2 — multi-tenant MCP platform complete
Steps 0–10 of the v2 plan, 194 tests passing.

Core infrastructure
- Shared Redis client (src/redis.ts); all four Redis consumers migrated
- Vitest test harness with vitest.config.ts and npm test/test:watch scripts

Billing & invoicing (Steps 1–2)
- Monthly invoice generation with idempotency (MySQL uq_customer_period unique key)
- Cron job with Redis distributed lock (Lua compare-delete, 1-hr TTL)
- Invoice emailer via nodemailer (FETCHERPAY SMTP)
- Billing middleware: checkLimit gate in handleToolCall; platform attribution fix

Email multi-tenancy (Step 3)
- EmailCtx = Account | EmailCredentials; imap.ts + smtp.ts accept both
- resolveEmailCtx helper in tools.ts; all email tools use customer credentials

Analytics + platform health (Steps 4–5)
- Chart.js bar charts for platform breakdown and daily activity
- Token expiry check in getCredential with dynamic import refresh
- platform-health.ts: per-platform health probe with 10-min Redis cache
- GET /api/health/platforms; "Token expired" amber badge in dashboard

Tool schema filtering (Step 6)
- stripAccountParam deep-clones tool schemas; multi-tenant sessions never
  see the internal account enum

OAuth hardening (Step 7)
- Atomic auth code consumption: UPDATE SET used=TRUE, check affectedRows
- customer_id threaded through oauth_auth_codes → oauth_tokens
- getTokenCustomer(); requireAuth resolves req.customer from Bearer token
- Consent page requires authenticated session; redirect_uri validated
  against registered URIs; http://localhost:* loopback wildcard

DCR browser flow (Step 8)
- ensureOAuthAppRegistered() upserts pre-registered SquareMCP OAuth app
  on startup with redirect URIs for mcp-callback, localhost:*, claude-desktop,
  opencode
- GET /oauth/connect-mcp → server-side redirect (client_id off frontend)
- GET /oauth/mcp-callback → exchanges code, renders config snippet page
  with copy buttons for Claude Desktop and Codex CLI

Webhooks (Step 9)
- webhook_url + webhook_secret columns on customers
- deliverWebhook(): HMAC-SHA256 signing, 3× exponential retry (1s/4s/16s),
  Redis DLQ with 7-day TTL on total failure
- isValidWebhookUrl(): SSRF protection (blocks RFC-1918, localhost, .local)
- POST /api/webhooks/config (secret returned once), GET, DELETE
- GET /api/admin/webhooks/dlq/:customerId
- WhatsApp POST route uses express.raw() for raw body preservation
- Dashboard Webhooks tab with secret-once display and copy button

Developer docs (Step 10)
- docs/ static HTML site (GitHub Pages, no build pipeline)
- index.html: landing page with client + platform overview
- getting-started.html: tabbed MCP config for Claude Desktop, Codex CLI, opencode
- platforms.html: LinkedIn, TikTok, WhatsApp, Instagram, Twitter, Telegram guides
- agent-tutorial.html: complete Node.js agent (Anthropic SDK + MCP SDK),
  LinkedIn posting loop, extensions for multi-platform + inbound webhook reaction

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 23:43:56 -04:00

Hermes MCP

Hermes MCP is a hosted MCP gateway for messaging, knowledge, and social connectors.

The production endpoint is:

https://hermes.squaremcp.com/mcp

Hermes currently supports MCP access patterns for:

  1. email
  2. Obsidian vault notes
  3. WhatsApp Business
  4. LinkedIn
  5. Telegram
  6. additional social connectors that are in various states of credentialing and rollout

What Hermes is for

Hermes is the integration and connector layer behind broader product work such as SquareMCP.

Use Hermes when you want:

  1. an MCP endpoint that exposes real tools over Streamable HTTP
  2. API-key or OAuth-protected access
  3. connector access from agent clients such as Codex CLI, Claude Code, opencode, or ChatGPT

Core transports

Transport URL
Streamable HTTP (preferred) https://hermes.squaremcp.com/mcp
Legacy SSE https://hermes.squaremcp.com/sse

Authentication

Hermes accepts:

  1. x-api-key header
  2. ?key= query parameter
  3. Authorization: Bearer ... for OAuth-based clients

For local/manual config examples in this repo, always substitute your own value for:

YOUR_MCP_API_KEY

Do not commit live API keys into repo config files.


Client setup guides

Use the setup guide that matches your client:

  1. Codex CLI setup
  2. CLI agent setup (Claude Code, generic MCP CLIs, Claude Desktop)
  3. opencode setup
  4. ChatGPT Custom GPT setup
  5. Social publishing setup (TikTok / Facebook)

Codex quick setup

Add this block to ~/.codex/config.toml:

[mcp_servers.hermes]
url = "https://hermes.squaremcp.com/mcp"

See CODEX_SETUP.md for the full notes and caveats.


opencode quick setup

Project-level opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "hermes": {
      "type": "remote",
      "url": "https://hermes.squaremcp.com/mcp",
      "headers": {
        "x-api-key": "YOUR_MCP_API_KEY"
      }
    }
  }
}

Full instructions: OPENCODE.md


Local development

npm install
cp .env.example .env
npm run dev
curl http://localhost:3456/health

The local server runs on port 3456 by default.


Deployment

Production deployment notes are in:

  1. DEPLOY.md
  2. hermes-k8s.yaml

SquareMCP product-site docs live under:

  1. product/site
  2. product/README.md
  3. videos/remotion-demo for SquareMCP video production assets and render workflows

Notes

The historical docs in this repo started from an email-only Claude-focused setup. Current deployment and setup guidance should follow:

  1. the hermes.squaremcp.com domain
  2. Streamable HTTP /mcp as the default transport
  3. the dedicated client setup docs linked above
Description
Hermes MCP / SquareMCP monorepo
Readme 22 MiB
Languages
TypeScript 75.8%
JavaScript 9%
HTML 7.5%
Python 3.9%
CSS 2.9%
Other 0.9%