
day3
io.github.MopraPublished by GitHub account Moprav1.0.0Updated Oct 24, 2026
Draft email campaigns in day3 from Claude Code, Cursor or VS Code as editable composer blocks.
The publisher's own server: Exit1 Uptime Monitoring
Overview
Day3's remote MCP server lets an assistant draft email campaigns that land in the Day3 app as editable composer blocks.
- What you can do
- Draft email campaigns from Claude Code, Cursor or VS Code, delivered into Day3 as editable composer blocks.
- Work within a small email tool for campaigns, audiences and transactional email, alongside the public API and webhooks.
- The server is stateless and tools-only, so the assistant's role is limited to drafting campaign content rather than sending.
- When to use it
- Useful when a small SaaS team already sends product updates or transactional email through Day3 and wants an assistant to draft campaign copy directly into the composer instead of pasting it in by hand.
- Requirements
- A remote endpoint at go.day3.app over Streamable HTTP. OAuth is required, with an Authorization header carrying a Bearer API key created in the Day3 app. A Day3 account and organization are needed; sending requires an active paid subscription and remaining monthly quota.
Installation
In SourceWeft
- Open day3 in the dashboard and add it to a workspace.
- Connect the required credentials. They are stored privately and never shown on public pages.
- Enable the server for the chats that should use its tools.
Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.
Use with an agent
Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.
Read https://sourceweft.com/mcp/io.github.Mopra%2Fday3/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.Other MCP clients
Add this to your client's mcpServers config. The client completes OAuth sign-in on first connect.
{
"mcpServers": {
"day3": {
"type": "http",
"url": "https://go.day3.app/api/mcp"
}
}
}README
Day3
Marketing and transactional email, billed by sends. $1/mo. No contact tax, no marketing suite to learn.
Source-available, not open source. This code is published for transparency and reference. See LICENSE for terms.
This repository is the Day3 product itself: the app at go.day3.app, the public REST API, the webhook and MCP endpoints, and the worker that sends the mail.
What it does
Day3 is a deliberately small email tool for small SaaS teams. Send product updates and changelogs to your users, and send your app's transactional email (password resets, receipts, magic links), through one verified domain, one monthly allowance, and one place to see delivery.
- Campaigns with a block composer, optional AI assist, scheduling, and per-send stats
- Audiences with segments (saved filters), topics (subscription categories), CSV import, and hosted signup forms
- Transactional email over
POST /v1/emails, Resend-compatible in shape, with per-email delivery status - Automations: onboarding and lifecycle flows drawn on a node canvas, published as immutable versions, unlimited on every tier
- Deliverability by default: verified sending domains, double opt-in, one-click unsubscribe, automatic bounce and complaint suppression, account auto-pause on bad reputation
- Metrics for deliverability, reputation and engagement, plus a searchable log of every email you ever sent
- Public API v1, signed webhooks, and an MCP server so Claude Code, Cursor or VS Code can draft a campaign that lands in Day3 as editable blocks
- Billed on sends, not subscribers. Free accounts set up domains, build audiences and send for real in sandbox mode. Paid plans buy the allowance to reach everyone else.
PRODUCT.md is the canonical description of what Day3 is, what it costs, and how every feature behaves. Read it before the code.
Tech stack
Quick Links
Built by Pradsgaard Labs. Also from the same workshop: exit1.dev, uptime monitoring.
Local development
Sign in with Clerk and create an organization, and you have a tenant. The campaign pipeline (review, generate recipients, batched queue sends, stats) works end to end locally.
Useful:
npm test: vitest against real Postgres (pglite). Applies migrations from scratch every run and asserts schema, journal and snapshots agree. Idempotency tests live here too.npm run typecheck/npm run lint/npm run buildnpm run db:generate: new Drizzle migration after schema changesnpm run db:studio: browse the local database
Migration discipline
src/db/schema.ts is the single source of truth. SQL under migrations/ is
forward-only and generated, never edited by hand. The journal
(migrations/meta/_journal.json) and the per-migration *_snapshot.json files
are part of the migration, so always commit them together.
Workflow when you change the schema:
- Edit
src/db/schema.ts. npm run db:generatewrites the nextNNNN_*.sql, its snapshot, and the journal entry.- Review the SQL (squash or rename within the same PR if the diff is noisy),
then commit the SQL and the
meta/changes in one commit. npm testproves it applies cleanly from scratch.
CI enforces this: it re-runs drizzle-kit generate and fails the build if that
produces any diff, meaning schema.ts and the committed migrations disagree or
a migration was added without its snapshot. Two contributors who both generate
a migration will collide on the next NNNN index. Resolve it by regenerating
one off the merged schema.ts so the journal stays linear.
Apply order in production is drizzle-kit migrate (see the deploy
checklist), which replays only the un-applied journal entries against
DATABASE_URL and records them in the __drizzle_migrations table. Never
db:push, which diffs live and can drop columns.
Required environment variables
Both processes validate their environment at startup (src/lib/env.ts) and
refuse to boot if a required variable is missing or a secret is too short
(min 16 chars). This prevents the empty-key failure mode where an unset
UNSUBSCRIBE_SECRET would sign HMAC tokens with "" (forgeable unsubscribe
and one-click links) or an unset OAUTH_STATE_SECRET would void OAuth CSRF
protection. The Next web tier validates on first server module load
(instrumentation.ts). The worker validates in worker/index.ts before it
starts consuming.
See .env.example (web) and .env.worker.example (worker) for the full list,
including non-secret config: Clerk publishable and secret keys, Redis, Supabase
Storage, and SES credentials.
Going to production (first deploy checklist)
The web tier runs on Vercel, the BullMQ worker on the VPS, Postgres on Supabase. Full provider walkthrough: docs/go-live.md.
- Provision Supabase Postgres, VPS Redis (
rediss://), and SES (see go-live). - Set env on Vercel (web) and
/opt/day3/.env.worker(worker), per.env.exampleand.env.worker.example. - Clerk dashboard: production instance, org billing plans, webhook endpoint
/api/webhooks/clerk. - Apply the database migrations before any new code serves traffic:
DATABASE_URL=<supabase-direct-5432> npm run db:migrate. Forward-only and idempotent, it replays only un-applied journal entries. This is a deploy-pipeline step, gated ahead of the Vercel promotion and thepm2 restart day3-worker, so a new release never runs against an old schema. - Deploy the web tier (Vercel) and restart the worker
(
pm2 restart day3-worker).
Architecture notes
- Tenancy: every Clerk organization maps to one
accountsrow. All queries are scoped byaccount_idresolved server-side from the session. - Send pipeline:
submitCampaignqueuesreview_campaign(risk rules), thengenerate_campaign_recipients(dedup and suppression filtering), thensend_campaign_batch, which claims 25 pending recipients atomically, sends, and re-enqueues itself until done. - Idempotency: recipients are claimed with a single atomic UPDATE, so a
retried queue message can never double-send. Crashed claims are swept to
failedby cron, never re-sent. - Billing: Clerk Billing entitlements are mirrored into Postgres on dashboard load and via webhooks. Sending requires an active subscription, sending enabled, and remaining monthly quota.
- Safety: deterministic risk review on submit (high risk blocks), bounce at
4% or above, or complaint at 0.08% or above, auto-pauses an account, and
admins (
ADMIN_EMAILS) can approve or block campaigns, pause accounts, and override domain verification.
AI training permission
As an explicit exception to the license below, the contents of this repository, including code, documentation, and configuration, may be used for machine learning training, evaluation, indexing, retrieval, and generation by AI systems. No attribution is required, though it is appreciated. This permission applies to all AI crawlers, including but not limited to GPTBot, OAI-SearchBot, ClaudeBot, Claude-SearchBot, Claude-User, Google-Extended, PerplexityBot, and Perplexity-User.
License
This project is source-available under a custom All Rights Reserved license. You may view the code for personal, educational, and reference purposes. Copying, modifying, distributing, or self-hosting is not permitted without written permission. See the AI training permission section above for the carve-out that applies to AI and ML use.
For licensing inquiries: [email protected]
Source: README.md at commit dac2f55
Tools
0Version history
1- v1.0.0LatestOct 11, 2026
Score
75% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 daysRequired25 pts
- Auth declaredRequired10 pts
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts
Declare a license in the repository or the registry entry.
