smtp-mcp-wrapper

smtp-mcp-wrapper

A minimal MCP server that provides a send_email tool for sending HTML email through an SMTP relay.

Category
Visit Server

README

smtp-mcp-wrapper

A minimal, self-hosted MCP server that exposes a single send_email tool. It sends real HTML email through an SMTP relay (e.g. Gmail). The tool is served over the streamable-HTTP MCP transport at /mcp, with an unauthenticated /healthz liveness route. The implementation is intentionally tiny (stdlib smtplib) to keep the audit/attack surface small.

⚠️ Security requirement: this server MUST be gated by an authorization service

This server implements no authentication of its own, by design. Anyone who can reach /mcp can send email. Do not expose it directly to the internet or bind it to a public port.

It must sit behind an identity-aware authorization proxy — such as Pomerium in MCP mode, or an equivalent like Cloudflare Access or oauth2-proxy — that authenticates and authorizes every request before it reaches /mcp.

Reference topology:

edge tunnel → reverse proxy (TLS) → Pomerium (SSO + allowlist to a single identity) → smtp-mcp-wrapper
                                                                                        (internal network only)

The provided docker-compose.yml deliberately publishes no host ports and attaches the container only to the proxy's internal Docker network, so the server is unreachable except through the authorization proxy.

Defense in depth already built in (these complement, they do not replace, the proxy):

  • ALLOWED_TO hard-limits recipients, so even a misused tool cannot mail outside the allowlist.
  • Setting REQUIRE_POMERIUM_IDENTITY=true makes the app itself reject /mcp requests that arrive without a Pomerium identity header (x-pomerium-assertion by default) — a backstop in case the proxy is ever misconfigured or bypassed.

Configuration

All configuration is via environment variables. Copy .env.example to .env and fill in real values. .env is git-ignored and must stay that way — it holds the SMTP password. Nothing secret is baked into the image (credentials are injected at runtime), which is why the published container image can safely be public.

Variable Default Description
SMTP_HOST smtp.gmail.com SMTP relay host.
SMTP_PORT 587 SMTP relay port (STARTTLS).
SMTP_USER SMTP username.
SMTP_PASS SMTP password. For Gmail, use an App Password.
MAIL_FROM SMTP_USER From address.
MAIL_FROM_NAME Optional display name for the From header.
DEFAULT_TO Recipient used when the tool's to argument is omitted.
ALLOWED_TO Comma-separated recipient allowlist. Empty = any recipient allowed.
REQUIRE_POMERIUM_IDENTITY false Also enforce a Pomerium identity header at the app layer.
POMERIUM_IDENTITY_HEADER x-pomerium-assertion Header checked when the above is true.
HOST / PORT 0.0.0.0 / 8080 Server bind address/port.

The send_email tool

send_email(subject: str, html: str, to?: str, text?: str) -> str

Sends an HTML email. to falls back to DEFAULT_TO and must be within ALLOWED_TO when that allowlist is set. text is an optional plain-text alternative for non-HTML clients.

Run

cp .env.example .env      # then edit .env with real values
docker compose up -d

Health check:

docker compose exec email-mcp \
  python -c "import urllib.request; print(urllib.request.urlopen('http://localhost:8080/healthz').read())"
# -> b'ok'

Then add the email-mcp route to your authorization proxy (pathless upstream, e.g. to: http://email-mcp:8080, so the /mcp path passes through) and connect your MCP client to https://<your-host>/mcp.

Maintenance

Patches flow with near-zero manual effort:

  • Dependabot (.github/dependabot.yml) watches requirements.txt, the Dockerfile base image, and the workflow's actions, opening upgrade PRs weekly. Also enable Dependabot security updates in the repo's Settings → Code security.
  • CI (.github/workflows/build.yml) builds and pushes the image to GHCR on push to main, on Dependabot PRs, via manual dispatch, and weekly (Mon 06:00 UTC) with no-cache so the OS and Python patches are genuinely refreshed even without code changes.
  • On the host, pull the rebuilt image with Watchtower (the compose file already sets the opt-in label) or a cron running docker compose pull && docker compose up -d.

Links

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured