L4

lmol-4/alert-my-human

Developer tools
163 stars 0 forks Quality 56 Trend 46

Lightweight MCP server for sending multichannel alerts from agents to humans.

Overview

Let your agent notify you when a task finishes, a job fails, or it needs your attention. Send alerts through email, Slack, Telegram, SMS, or webhooks. A small MCP server for personal automations. No database, queue, or background service. Bring your own provider credentials; hosting and notification providers may charge for usage. Configure just one to begin. Leave the other variables unset. Set AUTH_API_KEY to a long random secret, separate from your provider credentials: Enter AUTH_API_KEY when prompted. Add your channel variables in the project's environment settings for Production, then redeploy so they take effect. Your endpoint is https:// /api/mcp. Copy .env.example to .env, set your key and channel variables, then run pnpm dev. The endpoint is http://localhost:3000/api/mcp. Keep the process running; a remote client cannot reach your computer's localhost. Use an MCP client that supports HTTP servers with custom headers.

README

alert-my-human

Let your agent notify you when a task finishes, a job fails, or it needs your attention. Send alerts through email, Slack, Telegram, SMS, or webhooks.

A small MCP server for personal automations. No database, queue, or background service. Bring your own provider credentials; hosting and notification providers may charge for usage.

Quick start (MCP server)

1. Choose a channel

Configure just one to begin. Leave the other variables unset.

Channel Variables Setup
email RESEND_API_KEY, SENDING_EMAIL, ALERT_EMAIL (comma-separated for several) Resend: API key and a verified sending domain
slack SLACK_WEBHOOK_URL Incoming webhook; treat the URL as a secret
telegram TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID Create a bot with @BotFather, message it, then read message.chat.id from getUpdates
sms TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_FROM_NUMBER, ALERT_PHONE_NUMBER Twilio; numbers in international format, e.g. +353...
webhooks WEBHOOK_URLS, optional WEBHOOK_SECRET See Webhooks

Set AUTH_API_KEY to a long random secret, separate from your provider credentials:

node -e "console.log(require('node:crypto').randomBytes(32).toString('hex'))"

2. Run the server

Vercel — no local server to keep running:

Enter AUTH_API_KEY when prompted. Add your channel variables in the project’s environment settings for Production, then redeploy so they take effect. Your endpoint is https:///api/mcp.

Locally — Node.js 24 and pnpm 12.9.1:

git clone https://github.com/LMol-4/alert-my-human.git
cd alert-my-human
pnpm install --frozen-lockfile

Copy .env.example to .env, set your key and channel variables, then run pnpm dev. The endpoint is http://localhost:3000/api/mcp. Keep the process running; a remote client cannot reach your computer’s localhost.

3. Connect your agent

Use an MCP client that supports HTTP servers with custom headers. For clients using mcpServers configuration:

{
  "mcpServers": {
    "alert-my-human": {
      "type": "http",
      "url": "https:///api/mcp",
      "headers": {
        "Authorization": "Bearer "
      }
    }
  }
}

Replace both placeholders; use the localhost URL for a local client. Keep the real token out of committed client configuration. Claude Code configuration guidance.

4. Send your first alert

Ask your agent: “Use alert-my-human to list my channels, then send a test alert through one of them.”

list_channels takes no arguments and also reports partly configured channels. Example send_alert arguments, if email is configured:

{
  "channels": ["email"],
  "title": "It works!",
  "message": "Your agent can reach you."
}

Required: channels, title (up to 250 characters), and message (up to 4000). Optional: severity (info, success, warning, error; default info), context (up to 20 string key/value pairs), and idempotencyKey (reuse it when retrying the same alert).

Results

Each channel gets its own result:

{ "destination": "telegram", "outcome": "accepted", "attempts": 1, "durationMs": 212, "providerId": "42" }
{ "destination": "email", "outcome": "unknown", "attempts": 1, "durationMs": 10003, "error": { "code": "TIMEOUT", "message": "No response within 10s" } }
Outcome Meaning
accepted The provider accepted it. This does not prove it was received or read.
rejected The provider or a pre-send check refused it.
unknown No clear answer, e.g. a timeout; it may have been delivered.
not_attempted Not sent, e.g. an unknown channel name.

Errors use a code (TIMEOUT, NETWORK, HTTP_ERROR, RATE_LIMITED, INVALID_PAYLOAD, ABORTED, UNKNOWN_DESTINATION, PROVIDER_ERROR) and a short message without URLs or credentials. send_alert returns them as structured content plus a text summary. It sets isError only when no destination accepted; on partial success, retry only the channels that failed.

Delivery behavior

  • Each attempt times out after 10 seconds, and a send stops starting attempts after 25 seconds.
  • At most two attempts per destination. Rate limits (429) and server errors (5xx) are retried, honoring the provider’s retry delay when it fits the deadline. Failures to connect are retried. 4xx responses are not.
  • Timeouts and dropped connections are not retried, since the provider may already have the alert. Exception: email with an idempotencyKey, which Resend deduplicates.
  • idempotencyKey is forwarded per destination as : to Resend and to webhooks. It is not a universal guarantee; duplicates are still possible.
  • Messages must fit each provider’s limit (Slack 3000 characters per section, Telegram 4096, SMS 1600) or are rejected before sending. Keep messages brief.
  • Nothing is stored and no work survives shutdown. Scheduling and durable retries are up to the caller.

Webhooks

WEBHOOK_URLS takes one URL or a comma-separated list. Name entries with name=url (for example home=https://...); unnamed ones are called webhook, or webhook-1, webhook-2, … when there are several. Each is its own destination with its own result. WEBHOOK_SECRET, if set, is sent as Authorization: Bearer .

Each receives a POST with Content-Type: application/json:

{
  "id": "5f0c1c1e-...",
  "severity": "info",
  "title": "Task complete",
  "message": "Your export is ready.",
  "context": { "job": "export" }
}

id is unique per send and stays the same across retries and destinations. context is optional. Redirects are not followed. Errors report only the HTTP status.

If something goes wrong

Symptom Check
Unauthorized The server key and Bearer header match.
No channels listed All variables for a channel are set; restart locally or redeploy. list_channels names missing variables.
rejected with HTTP_ERROR Check credentials and recipient permissions. Except for webhooks, the message includes the provider’s reason.
INVALID_PAYLOAD Shorten the message or context for that channel.
Browser shows no page This is an MCP endpoint, not a website; connect through your client.

Development

pnpm check runs lint, types, and tests; pnpm build:checked adds a production build. Tests mock providers and send nothing real. To add a provider, add a factory in src/lib/providers.ts using the shared request helper, then register its variables in src/lib/env.ts.

The MCP tool arguments follow semantic versioning from 1.0; before then, minor versions may change them. Report security issues privately through GitHub security advisories. MIT license.

View this README on GitHub

Install

This server does not publish a one-line install command.

Open the repository installation guide

Configuration

{ "mcpServers": { "alert-my-human": { "type": "http", "url": "https://<your-domain>/api/mcp", "headers": { "Authorization": "Bearer <AUTH_API_KEY>" } } } }