No description
Find a file
2026-05-06 22:07:58 -04:00
deploy Initial mg-mcp: Mailgun MCP server (Streamable HTTPS) for optical-dev 2026-05-06 22:05:38 -04:00
.env.example Initial mg-mcp: Mailgun MCP server (Streamable HTTPS) for optical-dev 2026-05-06 22:05:38 -04:00
.gitignore Initial mg-mcp: Mailgun MCP server (Streamable HTTPS) for optical-dev 2026-05-06 22:05:38 -04:00
docker-compose.yml Initial mg-mcp: Mailgun MCP server (Streamable HTTPS) for optical-dev 2026-05-06 22:05:38 -04:00
Dockerfile Initial mg-mcp: Mailgun MCP server (Streamable HTTPS) for optical-dev 2026-05-06 22:05:38 -04:00
email_server.py Initial mg-mcp: Mailgun MCP server (Streamable HTTPS) for optical-dev 2026-05-06 22:05:38 -04:00
README.md Initial mg-mcp: Mailgun MCP server (Streamable HTTPS) for optical-dev 2026-05-06 22:05:38 -04:00
requirements.txt Initial mg-mcp: Mailgun MCP server (Streamable HTTPS) for optical-dev 2026-05-06 22:05:38 -04:00

mg-mcp — Mailgun MCP Server

A Streamable HTTPS MCP server that exposes a single send_email tool, backed by Mailgun (mg.oliver.solutions).

Deployed at: https://optical-dev.oliver.solutions/mg-mcp/

Architecture

LibreChat (or any MCP client)
   │  HTTPS, header: Authorization: Bearer <MCP_BEARER_KEY>
   ▼
Apache shared vhost on optical-dev.oliver.solutions
   │  ProxyPass /mg-mcp/  →  http://127.0.0.1:${MG_MCP_PORT}/   (prefix stripped)
   ▼
Docker container `mg-mcp`  →  uvicorn → FastAPI → FastMCP
   │  GET  /api/health   (no auth)
   │  POST /mcp          (MCP streamable HTTP, requires Bearer)
   ▼
Mailgun API

Stateless. No DB. No persistent volumes.

Local development

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env       # then edit and fill in real values
export $(grep -v '^#' .env | xargs)
python email_server.py     # serves on http://127.0.0.1:8000

Quick health check:

curl http://127.0.0.1:8000/api/health

Deploying to optical-dev.oliver.solutions

One-time setup:

  1. From a laptop, push this repo to GitHub:

    cd /Users/daveporter/Desktop/CODING-2024/MG-MCP
    git init && git add . && git commit -m "Initial mg-mcp"
    gh repo create OliverGroup/mg-mcp --private --source=. --push
    
  2. SSH into the dev server and clone to /opt/mg-mcp/:

    ssh user@optical-dev.oliver.solutions
    sudo git clone git@github.com:OliverGroup/mg-mcp.git /opt/mg-mcp
    sudo chown -R $USER /opt/mg-mcp
    cd /opt/mg-mcp
    
  3. Create .env from the template and fill in real values:

    cp .env.example .env
    nano .env
    
    • MAILGUN_API_KEY — the existing Mailgun private API key for mg.oliver.solutions
    • MAILGUN_DOMAINmg.oliver.solutions
    • MAILGUN_FROMnoreply@mg.oliver.solutions (or any verified address)
    • MCP_BEARER_KEY — generate with openssl rand -hex 32. Share with anyone configuring an MCP client.
    • Leave MG_MCP_PORT blank — deploy.sh will auto-pick.
  4. Run the deploy:

    bash deploy/deploy.sh
    

    It will print the chosen port, the public URL, and an Apache Include line.

  5. Add the printed Include line inside </VirtualHost> of /etc/apache2/sites-enabled/optical-dev.oliver.solutions.conf, alongside the other app Includes.

  6. Reload Apache:

    sudo apachectl configtest && sudo systemctl reload apache2
    

Re-deploy (after pushing changes to GitHub):

ssh user@optical-dev.oliver.solutions
cd /opt/mg-mcp
bash deploy/deploy.sh

Flags: --no-pull, --no-build, --logs.

Verification

From a laptop after deploy:

# 1. Health (no auth) — should return JSON
curl https://optical-dev.oliver.solutions/mg-mcp/api/health
# → {"status":"ok","service":"mg-mcp"}

# 2. MCP endpoint without auth — should 401
curl -i https://optical-dev.oliver.solutions/mg-mcp/mcp
# → HTTP/1.1 401, body {"error":"Missing Bearer token"}

# 3. MCP initialize handshake (replace TOKEN)
TOKEN=...your MCP_BEARER_KEY...
curl -i -H "Authorization: Bearer $TOKEN" \
     -H "Accept: application/json, text/event-stream" \
     -H "Content-Type: application/json" \
     -X POST https://optical-dev.oliver.solutions/mg-mcp/mcp \
     -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'
# → 200 with a streaming JSON response listing server capabilities

Configure a client (LibreChat)

Settings → MCP Connectors → Add:

Field Value
Name mailgun
MCP Server URL https://optical-dev.oliver.solutions/mg-mcp/mcp
Transport Streamable HTTPS
Authentication API Key
Header Format Bearer
API Key the value of MCP_BEARER_KEY from the server's .env

Save, then prompt: "Send an email to me@example.com with subject 'mg-mcp test' and body 'It works.'"

Troubleshooting

  • /mcp returns 404 — the FastMCP SDK version may serve at a different sub-path. Check docker compose logs app for the actual route, or try / instead of /mcp in the client URL.
  • Streaming responses hang or truncate — confirm flushpackets=on is in the rendered apache-mg-mcp.conf and that mod_proxy_http is loaded (sudo a2enmod proxy proxy_http headers && sudo systemctl reload apache2).
  • Health 200 locally, 502 publicly — the Include line is missing from the vhost or Apache wasn't reloaded.
  • Mailgun 401 inside the tool — the API key in .env is wrong; restart the container after fixing (docker compose up -d).