Skip to main content
Glama

notifs

A tiny local notification relay for agents, scripts and humans.

Anything can POST one event; notifs deduplicates it, matches rules, and fans it out to your channels. It also hosts your long-running monitor programs, and exposes an MCP server so an agent can notify you without you pasting anything.

agent / script / service ──POST──▶ notifs ──▶ desktop / Feishu / ...
                                      │
                              dedup · rules · retry · outbox

One process, one SQLite file, binds 127.0.0.1 only.

Install

npm i -g notifs

notifs init                 # 建数据目录 + 一个 agent token(~/.config/notifs/token)
notifs channel add desktop --kind local --config '{}'
notifs rule add --name all --when '{}' --actions '[{"channel":"desktop"}]'
notifs notify "hello"
notifs install-service      # systemd 用户服务 + 开机自启

Related MCP server: Channels MCP

The whole contract

POST http://127.0.0.1:7710/api/v1/events
Authorization: Bearer <token>        # ~/.config/notifs/token
Content-Type: application/json

{"type":"experiment.finished","text":"loss 2.10→0.83 · 3h12m · ~/models/x.pt"}

Only type and text are required. Unknown fields are rejected (strict). Returns 202 {accepted,deduplicated,dispatches,event_ids} — deduplicated:true is also success, don't retry.

type is dotted and hierarchical (disk.low, github.pr.reply); rules match it with * globs. Give an explicit dedup_key whenever you can decide "this is the same thing" — e.g. train:<runId>:epoch:100 (include the run id, or a re-run will never notify again).

Full contract: notifs contract.

Ask — send, then wait for a reply

POST /api/v1/ask
Authorization: Bearer <token>
Content-Type: application/json

{"text":"Run the full sweep now?","timeout_minutes":10}
202 {"ask_id":"01M...","event_id":"01M...","expires_at":"...","dispatches":1}

The notification goes out through the normal rules. When you quote-reply that message in Feishu, the ask gets answered — and the caller gets your words back:

GET /api/v1/ask/01M...?wait=300        # long-poll, server caps `wait` at 600s
{"status":"answered","reply":"go ahead, small run first","replied_at":"...","expires_at":"..."}

status is pending → answered | expired. Default timeout 5 minutes, max 30.

Two things to know:

  • You must quote-reply the notification. A plain message carries no parent_id, so there is nothing to match it against.

  • The reply has to come back over a channel that can receive: feishu-app plus the inbound long-connection producer. A group bot webhook (feishu) is send-only.

The MCP tool ask does all of this in one call and returns the reply text.

Three ways to write a producer

when

how

Script

you already have cron/systemd, or it's 20 lines

just POST. No SDK, no registration beyond a token

Managed

you want notifs to own the process

notifs watcher init <slug> → fill producer.json + index.mjs → watcher check/try/enable

Poller

plain HTTP + "new item / field changed / threshold"

notifs watcher init <slug> --kind poller, fill the poller field, no code

Managed producers get: auto-start, 30s heartbeat, crash backoff-restart, encrypted credential injection, log capture under the data dir.

The honest trade-off: a script nobody supervises can die silently — you just stop getting notifications, and "no notification" is indistinguishable from "nothing happened". That's why managed mode exists.

Example producers

Two runnable examples live in the repo — not in this package, because a producer is a program, not library code:

Directory

What it does

Deps

producers/routine

time-based reminders

none

producers/feishu-events

receives Feishu messages (long connection) → acks / ask

@larksuiteoapi/node-sdk

git clone https://github.com/Rottenwooood/notifs.git
cp -r notifs/producers/routine ~/.local/share/notifs/producers/
cd ~/.local/share/notifs/producers/routine && npm install   # only if it declares deps
notifs watcher sync && notifs watcher enable routine

Sending to Feishu is not a producer — that's the built-in feishu / feishu-app channel. feishu-events only brings messages back (you need it for ask and acks).

MCP

{
  "mcp": {
    "notifs": {
      "type": "local",
      "command": ["notifs", "mcp"],
      "environment": { "NOTIFY_BASE_URL": "http://127.0.0.1:7710" }
    }
  }
}

Exposes 4 tools — send, events, deliveries, status (the last answers "did it actually reach my phone?") — 3 prompts (write-script, write-monitor, poller) and one resource (notifs://contract).

Tools are deliberately not able to delete rules or rotate tokens: the blast radius of a confused agent is "one extra notification".

Full setup (opencode + any MCP client, all five tools, prompts, resources): docs/mcp.md.

Channels

kind

status

local

maintained — Linux desktop notifications

feishu

maintained — Feishu group bot webhook

feishu-app

maintained — Feishu app bot (DM or group)

ntfy bark wecom webhook

in the code, untested — no promises

Known limits

  • At-least-once delivery. Crash recovery can resend; messages carry event_id for downstream dedup.

  • No public ingress. Binds 127.0.0.1; remote senders need a proxy or a different bind.

  • at is a timestamp label, not a scheduler. There is no built-in cron. Time-based reminders are just a producer that watches the clock.

  • No throttling / quiet hours yet. Rate-limit on the producer side.

  • No feedback loop. Notifications are one-way; there's no ack/button round-trip.

中文文档

Development

pnpm install
pnpm typecheck && pnpm test
pnpm build          # → dist/cli.mjs, dist/server.mjs(esbuild 单文件,只外置 better-sqlite3)

License

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Exposes tools to send notifications, list channels, and check gateway health via the Model Context Protocol.
    0
    1
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables agents to send structured notifications to recipients via configurable channels (initial SMTP provider) without exposing delivery addresses or credentials, with tools for listing recipients, listing channels, and sending notifications.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to send notifications to a unified feed, report activity, request input from humans, and manage notification state through MCP tools.
    24 PyPI
    4
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables agents and applications to send notifications through configurable channels such as Telegram or a JSONL file, with queued delivery, status tracking, idempotency, and event-based routing.
    2
    MIT