Agentic-first notification hub. Send notifications via email, webhook, and Slack through a plain-text HTTP API designed for AI agents to drive.
- The agent IS the interface — No UI, no SDK. The API is the product.
- Plain text by default — One labeled, grepable line per record. Token-cheap.
- Instructive errors — Every 4xx includes a hint telling the agent what to do next.
- Self-documenting —
GET /helpreturns a one-page operating manual. - Simple auth — OTP via email → long-lived bearer token.
- Single static binary — Go + JSON file storage, zero external dependencies.
- Zero config defaults — Runs out of the box.
- Multi-tenant ready — Workspaces, audit logs built in.
- MCP connector — Speaks Model Context Protocol at
/mcp.
# Build
make build
# Run (defaults to :7100, data in ./data)
./notifykit
# Or with SMTP for real email delivery
NOTIFYKIT_SMTP_HOST=smtp.gmail.com \
NOTIFYKIT_SMTP_PORT=587 \
NOTIFYKIT_SMTP_USER=you@gmail.com \
NOTIFYKIT_SMTP_PASS=app-password \
NOTIFYKIT_SMTP_FROM=you@gmail.com \
./notifykit# 1. Request OTP
curl -X POST http://localhost:7100/auth/request \
-H 'Content-Type: application/json' \
-d '{"email":"user@example.com"}'
# 2. Verify OTP → get bearer token
curl -X POST http://localhost:7100/auth/verify \
-H 'Content-Type: application/json' \
-d '{"email":"user@example.com","code":"123456"}'
# → token=abc123... workspace=ws_xxxx
# 3. Use token
curl http://localhost:7100/channels \
-H 'Authorization: Bearer abc123...'Without SMTP configured, OTP codes are logged to stderr for dev/testing.
| Method | Path | Description |
|---|---|---|
| POST | /channels |
Create channel (email/webhook/slack) |
| GET | /channels |
List channels |
| GET | /channels/{handle} |
Get channel |
| PATCH | /channels/{handle} |
Update channel |
| DELETE | /channels/{handle} |
Delete channel |
| Method | Path | Description |
|---|---|---|
| POST | /notifications/send |
Send notification |
| GET | /notifications |
List notifications |
| GET | /notifications/{handle} |
Get notification |
| DELETE | /notifications/{handle} |
Delete notification |
| Method | Path | Description |
|---|---|---|
| GET | /help |
Operating manual |
| GET | /.well-known/agent.md |
Same as /help |
| GET | /workspace |
Workspace info |
| GET | /audit |
Audit log |
| POST | /mcp |
MCP (JSON-RPC 2.0) |
Plain text by default — one record per line with key=value pairs:
handle=chan_abc12 type=email name=Alerts target=ops@example.com active=true
handle=chan_def34 type=webhook name=CI Hook target=https://example.com/hook active=true
JSON via Accept: application/json header or ?format=json query param.
error: channel not found | hint: list channels with GET /channels to see available handles
| Env Var | Default | Description |
|---|---|---|
NOTIFYKIT_ADDR |
:7100 |
Listen address |
NOTIFYKIT_DATA_DIR |
./data |
Data directory |
NOTIFYKIT_SECRET |
random | HMAC secret for tokens |
NOTIFYKIT_SMTP_HOST |
(empty) | SMTP host |
NOTIFYKIT_SMTP_PORT |
587 |
SMTP port |
NOTIFYKIT_SMTP_USER |
(empty) | SMTP username |
NOTIFYKIT_SMTP_PASS |
(empty) | SMTP password |
NOTIFYKIT_SMTP_FROM |
(empty) | From address |
notifykit speaks Model Context Protocol at POST /mcp:
{"jsonrpc":"2.0","id":1,"method":"initialize"}
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"send_notification","arguments":{"channel":"chan_abc12","subject":"Alert","body":"Server down"}}}Available MCP tools: create_channel, list_channels, delete_channel, send_notification, list_notifications, get_notification.
make test # run tests with race detector
make vet # run go vet
make build # build the binary
make run # build and runMIT