← Discover MCPs and Agents
S
MCPOtherMCP Registry

Surfing Dog Inbox

Message, ask for a quote or book a call with Surfing Dog, through its open-source inbox.

Links

README

From the repo.

Surfing Dog Inbox

An open-source, self-hostable typed inbox for businesses. It receives messages, quote requests, orders and bookings from people and from AI agents — through email, a web form, REST and MCP (and every agent protocol we can reasonably speak) — and turns them into structured items with a lifecycle that can be handled by rules, by the owner, or by the owner's own AI.

Status: 0.1, in production on our own instance. The core, the REST and MCP doors, email in, sessions, OAuth for the owner's AI, the owner app and its setup wizard, webhooks, feeds, signed receipts and network membership all work on both runtimes. An instance runs at https://inbox.surfingdog.ai and the network at https://network.surfingdog.ai. Read the decision records in docs/adr/ first.

  • apps/inbox — the product: a Hono server + React SPA that runs on Cloudflare Workers and on Node/Bun.
  • packages/core — domain model, state machines, rules, receipts (AGPL-3.0).
  • packages/platform — the five runtime interfaces (Db, Blob, Jobs, MailIn, MailOut) and their adapters.
  • packages/spec — manifest, receipt and review formats with test vectors (MIT).
  • packages/sdk — typed client for the public and owner APIs (MIT).
  • packages/ui — design tokens, glass utilities and the kit page.
  • docs/ — ADRs and plans.

Licence: AGPL-3.0 for the server and app; MIT for packages/spec, packages/sdk and the connector SDK.

Run it

pnpm install
pnpm dev            # Node, SQLite in ./data/inbox.db, http://localhost:8787
pnpm dev:workers    # the same app on workerd (D1, Queues, cron)
pnpm test           # every test on Node and on Workers

The Node build is one file: pnpm --filter @surfingdog/inbox build:server writes apps/inbox/dist/server.mjs. Run it with node server.mjs and these variables:

VariableWhat
INBOX_DBSQLite file (default ./data/inbox.db)
INBOX_PUBLIC_URLThe https URL people and agents reach you at. Behind a proxy set it, or pass X-Forwarded-Proto.
INBOX_STATICStatic files directory (the owner app)
INBOX_OWNER_EMAILComma-separated addresses that may create the first account by email link
INBOX_SECRET_KEYSeals connector credentials and webhook secrets. One long random string, or several comma-separated and newest first to rotate. Without it the instance runs as normal but refuses to store a secret.
CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_EMAIL_TOKEN, MAIL_FROMReal email through Cloudflare Email Service (MAIL_FROM_NAME optional)
RESEND_API_KEYReal email through Resend instead; with neither, mail is printed to the console
PORT, HOSTListen address (default 8787 on all interfaces)

CLI: node server.mjs create-owner-key prints an owner API key, seed-demo adds a demo bike shop to an empty instance, seed-showcase the same shop with a week of items, network-ping reports to every network that is on now. pnpm --filter @surfingdog/inbox shots captures the owner app for the website.

Sign in at /login with an address from INBOX_OWNER_EMAIL (a link is emailed; in development the mail is printed to the console, so set INBOX_OWNER_EMAIL=you@example.com pnpm dev and copy the link) or with an owner key.

Email in

Every instance accepts raw MIME at POST /v1/email/inbound with the shared secret from Settings (email.inboundSecret) in X-Inbox-Email-Secret. Point a Mailgun route, a Postmark/SES inbound webhook or a forwarder at it. On Cloudflare, Email Routing delivers straight to the Worker's email() handler, no webhook needed. Messages are threaded by In-Reply-To/References, by a plus address (inbox+<item id>@…) or by a [SDI-<item id>] subject token, and deduplicated on Message-ID.

Join networks

Settings → Networks. An inbox can report to several networks, and each one lists it in its own directory. The setting is networks, a map keyed by each network's https origin, at most eight; settings are merged, so adding one leaves the others as they are, and switching one off is "enabled": false. A fresh instance lists https://network.surfingdog.ai, switched off; any directory that implements POST /v1/instances, POST /v1/instances/{domain}/ping and POST /v1/receipts works. For each network that is on, the instance registers its domain (the network verifies it by fetching /.well-known/agent-inbox.json and checking that instance is your https origin) and then sends, every hour, its software version, runtime and the number of bookings, orders, quotes and messages created in the last 24 hours. It also publishes every receipt it issues, which names the customer only by a pseudonym; no name, address or message content leaves the instance. Each network is called on its own, so one that is down never holds up another, and what it missed is sent when it answers again.

Config for your environment

Use the endpoint URL below in your config. No API key — you connect directly.

Tool

OS

Config file: ~/.cursor/mcp.json

{
  "mcpServers": {
    "mcp-server": {
      "url": "https://inbox.surfingdog.ai/mcp"
    }
  }
}

Paste into mcpServers in the config file. Restart Cursor after saving.

If this MCP is also published on mcpchannel.ai, you can subscribe from Browse and use the gateway config there instead.