
Newsletters where you pay for the emails you send, not for dormant subscribers, at a fraction of the
Newsletters where you pay for the emails you send, not for dormant subscribers, at a fraction of the price of beehiiv and the like. Open source: self-host it, or use mailcheap.ai.
·
Newsletters where you pay for the emails you send, not for dormant subscribers.
A fraction of the price of beehiiv and the like.
Website · API docs · Sign up for MailCheap Cloud
MailCheap is a newsletter app: write an issue, send it to your list, publish it on the web, from the dashboard or from your AI agent. This repository is the whole app. Self-host it with your own Amazon SES or PostShiba account, or use MailCheap Cloud, which runs this same code.
<slug>.mailcheap.ai), or on your server: every issue gets a page search engines can find, with a signup form, an author page, share images and a sitemap.hello@<slug>.mailcheap.ai.Feedback-ID for Gmail's feedback loop (its campaign or newsletter, its account, its kind), and once an admin connects Google Postmaster Tools, MailCheap reads it every day. An account Gmail flags at 0.08% has its sends paused, at 0.3% it's blocked, and the admins hear when the whole domain reaches 0.1%;| Write, review, send | The newsletter's website |
|---|---|
![]() | ![]() |
All names and addresses in the screenshots are made up.
| MailCheap Cloud | Self-hosted | |
|---|---|---|
| Price | From $19 a month for 20,000 emails | Free, plus what your provider charges per email: $0.10 to $0.16 per 1,000 on Amazon SES |
| Sending | Set up for you, from hello@<slug>.mailcheap.ai or your domain | Your Amazon SES or PostShiba account, from your domain |
| Website | <slug>.mailcheap.ai | /archive/<slug> on your server's domain |
| Who signs in | Anyone who signs up | The emails you allow |
| Limits | Emails a month and active subscribers, by plan | None |
| Setup | A few minutes | About an hour, most of it waiting for DNS and production access |
| Support | A chat in the dashboard | None: issues are off |
MailCheap Cloud is this repository with MAILCHEAP_CLOUD=true, which adds open sign-up, plans and Stripe billing. Only active subscribers count toward a plan, not the ones list cleanup marked dormant. Its marketing site (the landing, pricing and legal pages) isn't part of the open source. Every change to the app ships to both.
With your own sending account, you pay your provider for the emails you send: 10,000 readers and 4 issues a month is 40,000 emails, about $4 to $6 on Amazon SES.
Plan for about an hour, most of it waiting for DNS and for your provider to approve production sending. Self-hosting comes without support: issues are off and setup questions go unanswered.
| Service | For | Cost |
|---|---|---|
| MongoDB | Contacts, campaigns, stats | Free tier works |
| Amazon SES or PostShiba | Sending | SES: $0.10 to $0.16 per 1,000 emails, depending on its pricing plan. PostShiba: a fixed price per cluster, invite only for now |
| Upstash QStash | Background sending and scheduling | Free tier to start, then pay per message. One message sends 50 emails |
| Vercel or any Node.js 22+ host | Hosting | Free tier works |
| Resend (optional) | Sign-in codes and alerts. Without it, they go through SES or PostShiba | Free plan works |
| Upstash Redis (optional) | Rate limits shared by every server instance | Free tier |
| Amazon S3 with CloudFront, or Vercel Blob (optional) | Image uploads in the editor, the newsletter settings and the API | S3 and CloudFront: pay per use. Blob: free tier |
Without Redis, MailCheap counts the same rate limits in each server instance's memory. That still stops a script hammering a form, but on serverless hosts the limits aren't shared between instances and reset on each deploy. Add Redis before you put a signup form on a busy site. Without S3 or Blob, image uploads are off; HTML and Markdown campaigns can still use images hosted anywhere.
| Variable | What it does |
|---|---|
MONGODB_URI | MongoDB connection string with a database name |
BETTER_AUTH_SECRET | Signs sessions and every link in sent emails. 32+ random characters (openssl rand -base64 48), or the server refuses to start. Rotating it signs everyone out and breaks links in emails already sent |
SUPPRESSION_HASH_KEY | Keys the hashes of the never-email list every account shares. 32+ random characters of its own, never BETTER_AUTH_SECRET, or the server refuses to start, after an upgrade too. Changing it empties the list |
ADMIN_EMAILS | Comma-separated emails that can sign in and open /admin |
ALLOWED_EMAILS | Who else can sign in: addresses and @domain entries, comma-separated |
EMAIL_FROM | From address of sign-in codes and alerts, on a domain your Resend account or email provider verified |
APP_URL | Public URL of the app, for email links and sign-in. On Vercel it defaults to the production domain |
RESEND_API_KEY | Optional: sign-in codes and alerts through Resend. Without it, they go through the email provider |
SENDING_ENABLED | Nothing goes to readers unless it's true. Sign-in codes and alerts don't wait for it |
SES_* or POSTSHIBA_* | The email provider, in step 4 |
QSTASH_* | Background sending and scheduling, in step 5 |
.env.example lists every variable with what it does, the optional ones included: Google sign-in and Postmaster Tools, image uploads, Redis, Telegram alerts, the shared domain, and MailCheap Cloud's own.
0.0.0.0/0. Vercel doesn't have fixed IP addresses.?, like ...mongodb.net/mailcheap?retryWrites=true. That's your MONGODB_URI.MONGODB_URI, BETTER_AUTH_SECRET (at least 32 characters; generate it with openssl rand -base64 48), SUPPRESSION_HASH_KEY (generated the same way, another value), ADMIN_EMAILS (your email) and EMAIL_FROM (like MailCheap <[email protected]>, on a domain your Resend account or email provider verified). With a short secret, MailCheap refuses to start and the logs say why.EMAIL_FROM's domain there and add RESEND_API_KEY. Without it, codes go through SES or PostShiba once step 4 is done.https://<your-project>.vercel.app/signin and sign in with your email.Sending stays off until you finish the next steps, so nothing goes out to readers by mistake. On any other Node.js host: npm ci && npm run build && npm start, with the same variables, behind HTTPS. /api/health answers 200, or 503 with what to fix.
If you plan to use your own domain for the dashboard (like mailcheap.example.com), add it in Vercel now and set APP_URL to it. Links in your emails use APP_URL, so it should be final before your first send.
Only the emails you list: ADMIN_EMAILS (who can also open /admin) and ALLOWED_EMAILS, a comma-separated list of addresses and whole domains, like [email protected], @example.org. It's checked at every sign-in, with a code or with Google, and anyone you take off the list is signed out and loses their API keys at their next request. With both lists empty, nobody can sign in.
Everyone gets an account of their own, with up to 3 newsletters and their contacts and campaigns, and the account's domains and API keys. There's no billing on a self-hosted server: no plans, no limits.
Pick Amazon SES or PostShiba (invite only for now). EMAIL_PROVIDER picks one; without it, MailCheap uses PostShiba when POSTSHIBA_API_KEY is set and SES otherwise. Every account gets its own tenant there, with its own domains, suppression list and pause switch. MailCheap creates them; you set up the provider account and its events once.
Use one AWS region for everything below (the examples use us-east-1). An AWS account just for MailCheap is best: SES reputation and limits are per AWS account.
mailcheap-ses-events, and switch it to signature version 2, which signs messages with SHA256 instead of SHA1: aws sns set-topic-attributes --topic-arn <topic-arn> --attribute-name SignatureVersion --attribute-value 2. Then Create subscription with protocol HTTPS and endpoint https://<your-app>/api/webhooks/ses, raw message delivery off. MailCheap confirms the subscription by itself once it's deployed with the variables of step 4.{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ses:SendEmail",
"ses:GetAccount",
"ses:CreateTenant",
"ses:GetTenant",
"ses:DeleteTenant",
"ses:TagResource",
"ses:CreateTenantResourceAssociation",
"ses:DeleteTenantResourceAssociation",
"ses:UpdateReputationEntityPolicy",
"ses:UpdateReputationEntityCustomerManagedStatus",
"ses:CreateConfigurationSet",
"ses:CreateConfigurationSetEventDestination",
"ses:DeleteConfigurationSet",
"ses:CreateEmailIdentity",
"ses:GetEmailIdentity",
"ses:PutEmailIdentityMailFromAttributes",
"ses:DeleteEmailIdentity"
],
"Resource": "*"
}
]
}SES_REGION, SES_ACCESS_KEY_ID, SES_SECRET_ACCESS_KEY, SES_AWS_ACCOUNT_ID (the 12-digit account ID) and SES_SNS_TOPIC_ARN. Each account's configuration set publishes its events to that topic.https://<your-app>/api/webhooks/ses-tenants to it, and set SES_TENANT_SNS_TOPIC_ARN.Without Resend, sign-in codes and alerts go out through SES from EMAIL_FROM, outside every tenant, so its domain has to be verified in the AWS account before your first sign-in: Identities > Create identity > Domain, with Easy DKIM. In the sandbox, the addresses you sign in with have to be verified too.
PostShiba approves production sending by hand: until then, sends to anyone outside your team answer kyc_required (campaigns pause with that reason) and a team can have one cluster.
POSTSHIBA_API_KEY, with the team id as POSTSHIBA_TEAM_ID. Add a payment method (clusters need one).bulk cluster sends every email: its id goes in POSTSHIBA_BULK_CLUSTER_ID. Later, a transactional cluster in POSTSHIBA_TRANSACTIONAL_CLUSTER_ID takes welcome, confirmation and test emails, so they never wait behind a campaign. Set SEND_RATE_PER_SECOND to the bulk cluster's hourly cap divided by 3,600, less what welcome and test emails need when they share it. At a cap, PostShiba answers throttled: the batch goes back to the queue and QStash brings it after the hour.https://<your-app>/api/webhooks/postshiba with the events processed, delivered, deferred, bounce, dropped, spamreport and unsubscribe. Its secret goes in POSTSHIBA_WEBHOOK_SECRET.CREDENTIALS_ENCRYPTION_KEY, generated once with openssl rand -base64 32. It encrypts each tenant's SMTP password, and Postmaster Tools' refresh token.MailCheap creates the rest: a tenant per account (slug mc-<accountId>), an SMTP credential for it on each cluster (one in all on a single cluster), and its domains. Creating credentials and domains and running domain checks share PostShiba's budget of 60 an hour per key; a failed setup is retried at the account's next send.
Without Resend, sign-in codes and alerts go through a tenant of their own, mc-platform, on the transactional cluster. The first one adds EMAIL_FROM's domain there, and the server log lists the two CNAME records it needs; once PostShiba finds them, codes go out. A domain belongs to one tenant at PostShiba, so EMAIL_FROM needs a domain or subdomain that no newsletter sends from.
QSTASH_TOKEN, QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY (and QSTASH_URL if you picked a region other than the default).QStash calls APP_URL/api/jobs/... to send each batch, so the app has to be reachable on the internet. MailCheap checks QStash's signature on every job.
mail.example.com, so your main domain's email is unaffected. Add the DNS records it lists (DKIM, return path, and DMARC if your root domain has none), set to DNS only if your DNS is on Cloudflare, then click Check now.SENDING_ENABLED=true and redeploy.Google sign-in. Create an OAuth client (web application) with the redirect URI <APP_URL>/api/auth/callback/google, then set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET. The allowlist applies, and a Google sign-in joins an existing user only when Google verified that email.
Gmail's spam rates (Google Postmaster Tools). It needs the Google sign-in client above, CREDENTIALS_ENCRYPTION_KEY and CRON_SECRET; without them, or until someone connects, nothing runs.
<APP_URL>/api/admin/postmaster/callback to the client's authorized redirect URIs. Its consent screen has to be published (In production): in Testing, Google expires the connection after 7 days.SHARED_DOMAIN, which PostShiba's primary domain signing adds to every email, or POSTMASTER_DOMAIN. A domain the same Google account verified in Search Console is verified already./admin, under Gmail spam rates, click Connect and allow access with that Google account. Google warns that it hasn't verified the app: it's your own, continue. MailCheap asks for read access to traffic statistics only, and stores the refresh token encrypted with CREDENTIALS_ENCRYPTION_KEY.Vercel Cron then runs /api/cron/postmaster every day (vercel.json); elsewhere, have a scheduler call it with Authorization: Bearer <CRON_SECRET>. It acts on the newest day of Gmail's data once, with the thresholds in POSTMASTER (lib/config.js). Gmail only reports domains that send to at least 50 Gmail users a day, and a feedback ID once it has enough emails and spam reports, so until then it finds nothing and says nothing. If Google refuses the connection, one alert says so. Every email's Feedback-ID is <campaign or newsletter id>:mc-<accountId>:<kind>:mailcheap (lib/sending-rules.js): SES sends it as it is, and PostShiba writes its own in its place, also led by mc-<accountId>, so each ID maps back to its account (lib/postmaster-rules.js).
Image uploads. The quickest is Vercel Blob: in Vercel, Storage > Create > Blob, connect it to the project, and redeploy. To serve images from a subdomain of your own (like cdn.example.com), put an S3 bucket behind CloudFront. It takes over new uploads, and images already on Blob keep their URLs:
Create a private S3 bucket with Block Public Access on.
In ACM, request a certificate for the subdomain in us-east-1, validated by DNS. If your domain has CAA records, add 0 issue "amazon.com".
Create a CloudFront distribution: the bucket as origin through Origin Access Control (add the bucket policy CloudFront gives you), viewer protocol HTTPS only, the CachingOptimized cache policy, and the subdomain as alternate domain name with that certificate. Point the subdomain at the distribution with a CNAME.
Create an IAM user for MailCheap with this policy, then an access key for it. Deleting an account deletes its images and clears them from CloudFront's cache, hence s3:DeleteObject and cloudfront:CreateInvalidation:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::<bucket>/accounts/*"
},
{
"Effect": "Allow",
"Action": ["cloudfront:CreateInvalidation"],
"Resource": "arn:aws:cloudfront::<aws-account-id>:distribution/<distribution-id>"
}
]
}Set IMAGES_S3_BUCKET, IMAGES_S3_REGION, IMAGES_S3_ACCESS_KEY_ID, IMAGES_S3_SECRET_ACCESS_KEY, IMAGES_CDN_URL (like https://cdn.example.com) and IMAGES_CLOUDFRONT_DISTRIBUTION_ID (the distribution's ID), and redeploy. Builds read IMAGES_CDN_URL too.
Each image gets a name that never changes and Cache-Control: public, max-age=31536000, immutable, so CloudFront and browsers keep it for a year. An account's purge invalidates its folder, /accounts/<accountId>/*, on the distribution, so CloudFront stops serving its deleted images.
Shared rate limits. Create a Redis database in the Upstash console and add UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN.
Alerts on Telegram. Every admin alert shows on /admin and is an email to ADMIN_EMAILS, except the email provider refusing one account's login, which only shows on /admin unless a second account's is refused within the hour. The ones that need someone (an automatic account block, the email provider refusing MailCheap's sends or holding a tenant, Gmail's spam rate for the domain reaching 0.1% or Postmaster Tools refusing the connection, sign-in codes, Stripe events, webhooks or background jobs failing, QStash refusing jobs, shared addresses and the DNS helper) can reach Telegram too: create a bot with @BotFather, send it a message, and set TELEGRAM_BOT_TOKEN and the chat's id as TELEGRAM_CHAT_ID. Each alert goes there at most once every 6 hours. On PostShiba, have a scheduler call /api/cron/hourly every hour with Authorization: Bearer <CRON_SECRET> (Vercel Cron sends it once CRON_SECRET is set): it checks the team's status (a suspension, the approval, clusters at their cap, held tenants) and alerts on what stops sending, and looks at each verified sending domain's DNS records once a day, so a record that's gone or behind a proxy stops that domain and emails its owner. Its first run with Telegram set up posts "Telegram alerts are on".
Shared domain. SHARED_DOMAIN is how MailCheap Cloud gives every newsletter without a domain of its own an address, hello@<slug>.SHARED_DOMAIN, and its website at <slug>.SHARED_DOMAIN. MailCheap adds each subdomain at the provider and has its records published, and removed when the slug changes, by a DNS helper (DNS_BROKER_URL, DNS_BROKER_SECRET): on MailCheap Cloud a Vercel project of its own that holds the Vercel token, so the app never does, and only writes a shared address's records and puts website domains on the app's project. The helper isn't part of this repository, and without one DNS automation is off and shared addresses can't be set up. Its DNS has to be on Vercel, with *.SHARED_DOMAIN on the project. Add one DMARC record for the whole domain yourself: _dmarc.SHARED_DOMAIN TXT v=DMARC1; p=none;. It can be the app's own domain, as MailCheap Cloud's is mailcheap.ai: slugs can't take www or the other names in lib/reserved-slugs.js, and those hosts never open a website.
Websites on your own domains. Set ARCHIVE_CNAME_TARGET to the host your server answers on (cname.vercel-dns.com on Vercel), and each newsletter's Website settings offer a subdomain of your own, like news.example.com. Add that subdomain to your Vercel project (or your web server) first, then add it in MailCheap with the TXT record it shows: once its CNAME and the TXT record are found, the website and the links in the newsletter's next emails move there.
mail.example.com), so a bad week doesn't affect your main domain's email./admin and MailCheap holds each account to the same levels there.MAILCHEAP_CLOUD=true is what mailcheap.ai runs with: sign-up open to anyone, a newsletter setup at /welcome right after sign-in, a dashboard to try before paying with a paywall on sending, imports, domains and API keys, plan limits, and MailCheap's own emails through Resend only. It refuses to start without STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET and RESEND_API_KEY, and /api/health answers 503 with the reason, so the cloud can't run without billing by mistake. Set MAILCHEAP_CLOUD for builds too: the public pages read it then.
| Plan | Monthly | Yearly | Emails per month | Active subscribers |
|---|---|---|---|---|
| Starter | $19 | $190 | 20,000 | 10,000 |
| Growth | $39 | $390 | 75,000 | 40,000 |
| Pro | $79 | $790 | 200,000 | 100,000 |
| Scale | $149 | $1,490 | 500,000 | 250,000 |
| Max | $349 | $3,490 | 2,000,000 | 1,000,000 |
| Ultra | $799 | $7,990 | 5,000,000 | 2,500,000 |
lib/plans.js is the one place these live. Yearly plans get the monthly allowance every month of the paid year. Every email counts toward the month: issues, tests, welcome and confirmation emails. Over a limit, campaigns stop with a clear message and an upgrade link; signups and confirmation emails keep going. Welcome emails take room in the month's emails like issues: once they're used up, each one is skipped (its Message says why), the owner gets one email that month, and the dashboard says so next to the welcome email, on the overview and on the billing page. They start again when the month resets or the plan grows; the skipped ones aren't sent later. Admin overrides replace a plan's numbers for one account.
Admins can give an account a free plan from /admin (the account's menu, Give a free plan): any of the six, with an optional end date, without Stripe. It works like a paid plan, its emails start over every month from the day it was given, and the billing page and get_billing (REST API and MCP) show it. A plan the account pays for takes over while there's one. End free plan, or its end date, stops it like a canceled plan: the data stays and sending stops.
mailcheap_<plan>_monthly and mailcheap_<plan>_yearly, like mailcheap_growth_yearly. Checkout finds prices by these keys and refuses one whose amount or interval doesn't match lib/plans.js, so no price ID goes in the environment. A plan shows on the pricing pages, the paywall, billing and get_billing only once Stripe has both of its prices at those amounts: the app reads them every 10 minutes, and the static pages when they're built, so redeploy after adding one.<APP_URL>/api/webhooks/stripe with the events checkout.session.completed, customer.subscription.created, customer.subscription.updated, customer.subscription.deleted and invoice.paid. Use API version 2026-09-30.endive (the one stripe@23 pins) and put its signing secret in STRIPE_WEBHOOK_SECRET.Every subscription event re-reads the subscription from Stripe, so events arriving out of order can't leave stale data. Canceled accounts keep their data: sending, signups and the website stop, and everything comes back when they subscribe again.
Create a key on the API keys page and send it as Authorization: Bearer <key>. A full access key can do everything the dashboard can; a signups only key can only add contacts, for keys that sit in a website's code. Every key gets 300 requests a minute.
Add a contact: POST /api/v1/contacts
curl -X POST https://<your-app>/api/v1/contacts \
-H "Authorization: Bearer $MAILCHEAP_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","source":"website","ip":"203.0.113.7"}'MCP: connect Claude Code with a full access key. Every action is a tool.
claude mcp add --transport http --scope user mailcheap https://<your-app>/mcp \
--header "Authorization: Bearer $MAILCHEAP_API_KEY"ChatGPT, Claude and Grok Bot add https://<your-app>/mcp as a connector or custom MCP server and sign in with OAuth: you sign in to MailCheap and allow the app on a consent page, and it gets full access to that account. The API keys page lists connected apps and revokes them. They need the server to be reachable over HTTPS from the internet.
/docs on your server has every endpoint, the errors, the MCP setup for ChatGPT, Claude, Grok Bot, Claude Code, Codex and Cursor, and the OpenAPI document at /api/v1/openapi.json. On MailCheap Cloud, the same at mailcheap.ai/docs and https://mailcheap.ai/mcp.
Read AGENTS.md first, whether you're a person or an AI agent: how the app is organized, MailCheap Cloud and self-hosting, the rules (no secrets or personal data in code, tests or commits), code style and tests. SECURITY.md covers what's built in and the known gaps. Issues are off, and pull requests may not be reviewed.
You need Node.js 22+ and MongoDB:
git clone https://github.com/marclou/mailcheap.git && cd mailcheap
npm install
cp .env.example .env.local # set MONGODB_URI, BETTER_AUTH_SECRET, SUPPRESSION_HASH_KEY, ADMIN_EMAILS
npm run devMAILCHEAP_CLOUD it runs as a self-hosted server: sign in with an email in ADMIN_EMAILS or ALLOWED_EMAILS. Without RESEND_API_KEY, development prints the code in the server console ([signin] Code for ...); production never does.docker run -d -p 27017:27017 mongo and MONGODB_URI=mongodb://127.0.0.1:27017/mailcheap. A replica set (mongod --replSet rs0, then rs.initiate()) also gives Better Auth transactions, like Atlas.MAILCHEAP_CLOUD=true with Stripe test keys and a Resend key: the cloud doesn't start without them. Run stripe listen --forward-to localhost:3000/api/webhooks/stripe and use its signing secret as STRIPE_WEBHOOK_SECRET.SENDING_ENABLED=true. SES needs SES_ACCESS_KEY_ID and SES_SECRET_ACCESS_KEY: the app never falls back to ~/.aws or other default AWS credentials. PostShiba needs its four ids and keys and CREDENTIALS_ENCRYPTION_KEY.localhost. To try a full send locally, run the QStash dev server (npx @upstash/qstash-cli dev) and use the URL, token and signing keys it prints.Before a pull request, run the full suite, lint and a build:
npm test # unit and integration tests
npm run lint
npm run buildIntegration tests start a throwaway mongod per file, so mongod has to be on the PATH (or set MONGOD_PATH). They import server actions and route handlers as they are, and tests/setup replaces every outside service with the stubs in tests/stubs, so nothing reaches the network. tests/parity.test.mjs fails when an action is missing from the REST API, MCP, the OpenAPI document, the docs or the llms files.
GNU Affero General Public License v3.0. Copyright (C) 2026 Marc Lou.
If you change MailCheap and run it for other people, the AGPL asks you to offer them the source of your version: point the "Source code" link (SOURCE_URL in lib/site.js) at it. The one-time release before this license, 67d13b0 in github.com/marclou/mailcheap's history, stays under MIT.
Made by Marc Lou.
Paste this prompt into your agent. It reads this page and does the setup for you.
Read https://aiagentslisting.com/mcp/mailcheap to learn what the "Mailcheap" MCP server does and how to install it. Add it to my coding agent's MCP configuration as documented on that page, then confirm the server connects and list the tools it exposes.Agents can also browse this directory over MCP at https://aiagentslisting.com/api/mcp
claude mcp add --transport http --scope user mailcheap https://<your-app>/mcpThis server doesn't publish a machine-readable tool manifest, and it doesn't expose a public endpoint we could ask. Connect the server locally to see what it exposes.
We could not run this server: its endpoint did not list its tools to an anonymous client, which usually means it asks for an API key or a sign-in. The four checks that need a live server are left out, and the grade tops out at B until we can read its tools.
Maintain this server? Claiming proves you own the listing and earns the last 4 points.
Claim this listingPaste this line near the top of your repository's README. The badge always renders the current score.
[](https://aiagentslisting.com/mcp/mailcheap)Nothing comparable is listed yet.
No tagged releases on record.
Connect to the AI Agents Listing MCP server at https://aiagentslisting.com/api/mcp using the HTTP transport and complete the sign-in when it asks. Then call the submit_review tool for the listing "mailcheap" with a rating from 1 to 5 and a short note on what worked and what did not.No reviews yet
Be the first to share your experience with this tool.
One email a week. New agents, MCP servers and skills, and what is actually getting traction.