Skip to main content

Stdio MCP server for sending email notifications via AWS SES

Project description

ses-email-notification

Stdio MCP server exposing a single send_email tool backed by AWS SES (SESv2 API).

Credentials come from boto3's default chain: the EC2 instance role in production, AWS_PROFILE for local testing. No credential configuration in code.

Tool: send_email

Parameter Type Required Notes
to list[str] yes one or more recipients
subject str yes
body_text str no* plain-text body
body_html str no* HTML body; both → multipart/alternative
cc list[str] no
attachment_paths list[str] no local file paths inside ATTACHMENT_BASE_DIR

*At least one of body_text / body_html is required.

Returns the SES MessageId on success. SES failures surface the SES error code and message verbatim (e.g. MessageRejected: Email address is not verified).

The sender address is fixed by configuration — the tool has no from parameter.

Configuration (environment variables)

Variable Required Purpose
SES_FROM_ADDRESS yes verified SES identity to send from
AWS_REGION yes region of the SES identity
ATTACHMENT_BASE_DIR no directory attachments may be read from; attachments are rejected if unset
AWS_PROFILE local only profile for local testing; omit on EC2 (instance role is used)

MCP client configuration

From PyPI (no checkout needed — uvx downloads and runs the published package):

{
  "mcpServers": {
    "ses-email-notification": {
      "command": "uvx",
      "args": ["ses-email-notification"],
      "env": {
        "AWS_REGION": "us-east-1",
        "SES_FROM_ADDRESS": "noreply@example.com",
        "ATTACHMENT_BASE_DIR": "/path/to/agent/output"
      }
    }
  }
}

From a local checkout (testing with an AWS profile):

{
  "mcpServers": {
    "ses-email-notification": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/ses-email-notification", "ses-email-notification"],
      "env": {
        "AWS_PROFILE": "your-profile",
        "AWS_REGION": "eu-central-1",
        "SES_FROM_ADDRESS": "noreply@example.com",
        "ATTACHMENT_BASE_DIR": "/path/to/agent/output"
      }
    }
  }
}

EC2 (instance role provides credentials — no AWS_PROFILE):

{
  "mcpServers": {
    "ses-email-notification": {
      "command": "uv",
      "args": ["run", "--directory", "/opt/ses-email-notification", "ses-email-notification"],
      "env": {
        "AWS_REGION": "eu-central-1",
        "SES_FROM_ADDRESS": "noreply@example.com",
        "ATTACHMENT_BASE_DIR": "/var/agent/output"
      }
    }
  }
}

IAM policy for the EC2 instance role

ses:SendRawEmail is required for attachments. Scope the resource to your verified identity ARN:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["ses:SendEmail", "ses:SendRawEmail"],
      "Resource": "arn:aws:ses:REGION:ACCOUNT_ID:identity/example.com"
    }
  ]
}

Limits & caveats

  • Raw messages (sends with attachments) are capped at 10 MB after base64 encoding (~7 MB of actual files); the server rejects oversized sends before calling SES.
  • SES sandbox: if the account is in sandbox mode, sends to unverified recipients fail with MessageRejected. Request production access before relying on this server.

Development

uv run pytest            # unit tests (botocore Stubber, no AWS calls)

# manual smoke send against real SES:
AWS_PROFILE=your-profile AWS_REGION=eu-central-1 \
SES_FROM_ADDRESS=noreply@example.com \
uv run mcp dev src/ses_email_notification/server.py

Publishing to PyPI

Bump version in pyproject.toml first — PyPI rejects re-uploads of an existing version.

uv build                                      # builds sdist + wheel into dist/
uv publish --index testpypi --token <token>   # dry run against test.pypi.org
uv publish --token <token>                    # real PyPI

Tokens come from https://pypi.org/manage/account/token/ (and the test.pypi.org equivalent). UV_PUBLISH_TOKEN works instead of --token.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ses_email_notification-0.1.0.tar.gz (5.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ses_email_notification-0.1.0-py3-none-any.whl (7.4 kB view details)

Uploaded Python 3

File details

Details for the file ses_email_notification-0.1.0.tar.gz.

File metadata

  • Download URL: ses_email_notification-0.1.0.tar.gz
  • Upload date:
  • Size: 5.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for ses_email_notification-0.1.0.tar.gz
Algorithm Hash digest
SHA256 80bf8c27ac2a49d78c3ce938c45f0099a2416d5b42c084154db33fa0935f71a0
MD5 13932897fd7c3c70ef9a831b8c126ef9
BLAKE2b-256 3393c577848ce7e3dfe1e7687f997e1966ce39e82de41211c5d049e060aefc56

See more details on using hashes here.

File details

Details for the file ses_email_notification-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: ses_email_notification-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 7.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for ses_email_notification-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d243117c2f2747a7715a8d10545ccf20ea260d2192e329e6b45d6e5a583cba2b
MD5 14b6b9e071ff73b487783eabd1aea5f7
BLAKE2b-256 af8dbc9064f0cd66894317d5af1825063648574477634e5959f9bfb39acc66ed

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page