Skip to main content
Glama
notify-human-mcp

notify-human-mcp

by Ruxconk

notify-human-mcp

An MCP server that gives your LLM a way to reach you on Discord whenever it needs your attention — a question it can't answer itself, a blocker, a decision it needs from you, something worth knowing mid-task, or work that's finished. Not just an end-of-task bell: a general human-attention channel. Every message arrives in a standardized format you control from a file, not from each model's habits.

The server reads your instructions file at every client launch and hands the text to the MCP client as its instructions field. The client injects it into the LLM's system prompt each session — the same effect as AGENTS.md, per tool. Edit the file, and the next session on that machine uses the new format. That text lives in the conversation history, so it is summarized away when the conversation is compacted; the send tool description therefore also carries the file path with a conditional hint to re-read it if the rules are no longer in context.

One tool is exposed:

Tool

Args

Behaviour

send

prose mode: message: str (required), embed: bool = False · template mode: status, title, body (required), ticket, model

Posts to your Discord webhook. Prose: embed=False → markdown text, embed=True → rich embed card; over the limit (2000 plain / 4096 embed) is rejected with the limit named, not truncated. Template: the server assembles the text, so shape errors are rejected with the reason. Returns a short status string.

If no webhook URL is configured, send fails with a clear error and posts nothing.

Install

Requires uv. The package is not on PyPI yet, so install from the repository:

uvx --from git+https://github.com/Ruxconk/notify-human-mcp.git notify-human-mcp

Related MCP server: Chat Human MCP Server

Per-machine setup

Add one block to your MCP client's config (Claude Desktop, Codex CLI, etc.):

"notify-human": {
  "command": "uvx",
  "args": [
    "--from",
    "git+https://github.com/Ruxconk/notify-human-mcp.git",
    "notify-human-mcp"
  ],
  "env": {
    "NOTIFY_HUMAN_WEBHOOK_URL": "https://discord.com/api/webhooks/…",
    "NOTIFY_HUMAN_INSTRUCTIONS_FILE": "/path/to/your-instructions.md"
  }
}

For a local checkout, replace the git URL with the directory path: "--from", "/path/to/notify-human-mcp".

Env var

Required

Meaning

NOTIFY_HUMAN_WEBHOOK_URL

yes

Your Discord webhook URL. Each machine/user gets its own.

NOTIFY_HUMAN_INSTRUCTIONS_FILE

no

Instructions file: .md/.txt = prose, .json = template (see below).

NOTIFY_HUMAN_INSTRUCTIONS_URL

no

Hosted instructions URL (prose only; fetched at startup).

Instructions are resolved in order: file → URL → built-in default. A missing file or failed fetch falls through silently — the server always starts.

Restart the MCP client after changing anything. A stdio server is one long-lived process: it reads its code, its env and the instructions file at launch and never looks again. Editing the instructions file, changing an env var, or shipping a new version does nothing until the client restarts the server — and when you install from a local path, uvx caches the built wheel per content hash, so a rebuilt package needs that same restart to take effect. If notifications come back in the old format after you edited the file, this is why.

Two instruction modes

Prose mode (default): a .md/.txt file of plain-language rules. The LLM reads them and tries to comply — flexible, zero setup, best-effort.

Template mode: point NOTIFY_HUMAN_INSTRUCTIONS_FILE at a .json file and the format is enforced by construction. send then takes named fields — status, title, body, optional ticket, agent, model, repo — and the server assembles the message from the template, so the shape cannot drift. An unknown status or a missing field is rejected with the reason, nothing posted. Structure:

{
  "header": "{time} | {repo} — {title} {status_emoji}",
  "lines": ["{ticket}", "agent: {agent} | model: {model} | Machine: {machine}"],
  "statuses": {"done": "✅", "blocked": "🛑", "question": "❓"},
  "max_chars": 1000,
  "embed": true,
  "guidance": "Address him as Rux. Short bullets, one fact each; no raw logs."
}

Only header and statuses are required. Placeholders for header/lines: time, repo, title, status_emoji, ticket_line, ticket, agent, model, machine. ticket_line renders ticket: X; ticket renders the raw value verbatim (e.g. ENG-142 — rotate deploy keys); agent names the agent sending the ping. A line that renders empty (no ticket, say) is dropped. max_chars is a hard ceiling on the rendered message. embed: true posts a rich card instead of a plain message, which lifts the Discord limit from 2000 to 4096 characters. guidance is free text appended to the instructions the LLM receives — the place for tone, persona and "when to ping" rules that a fixed structure cannot express. Working examples: examples/ (template-minimal.json, template-full.json, template-team.json) — copy one and edit the values. Startup logs the mode and source on stderr; if a prose file and a same-stem .json both exist, JSON wins, and a broken JSON file is reported loudly rather than silently downgrading to prose.

Writing the instructions file

This file is the format control — and it decides when the LLM may ping you, not just how. Example:

Use the `send` tool whenever the human's attention is needed: you are blocked, you
need a decision or missing information, something important happened mid-task, or
you finished. One message per event — no play-by-play.
Format: one-line status first (done / blocked / needs input / FYI), then a short
summary, then what you need from the human (if anything). Keep it under 1000
characters. No raw logs.

Point several machines at the same file contents (or the same hosted URL) to get one format everywhere; give a machine its own file to diverge.

Trust note: a hosted instructions URL is a control point — whoever can edit that URL controls what every connected LLM is told. Keep it private and writeable only by you.

Development

uv sync                          # env + dev deps
uv run pytest -q                 # 85 tests, HTTP mocked or loopback-only, zero real sockets
uvx ruff check src tests         # lint
uvx ruff format --check src tests
uv build                         # sdist + wheel into dist/

Publishing (prepared — not yet run)

First, create a PyPI account and (recommended) an API token scoped to the project. Then:

uv build                            # dist/notify_human_mcp-<ver>.tar.gz + .whl
uv publish                          # or: pipx run twine upload dist/*

Bump version in pyproject.toml for each release.

Optional, later: list the package in the public MCP Registry so others can discover it. The registry is still in preview, stores metadata only, and verifies repo ownership — a discovery nicety, never needed for your own machines.

License

MIT — see LICENSE.

Available Tools

1 tool
sendA

Send one notification to the human's Discord whenever their attention is needed: you are blocked, need a decision or missing info, have a question or warning about the current task, something important happened mid-task, you finished, or the user asked to be pinged. One message per event — do not spam the user. Keep it under 1000 characters: status line first, short bullets, the ask last. Messages over 2000 characters (plain) or 4096 (embed) are rejected, not truncated — shorten before sending. Set embed=True for a rich card instead of plain markdown.

NameRequiredDescriptionDefault
embedNo
messageYes

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses hard rejection limits (2000 plain / 4096 embed, 'rejected, not truncated'), the 1000-character soft target, and the required message structure. It does not state permissions or rate-limit semantics beyond the anti-spam guidance, so it stops short of fully rich behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is front-loaded with the purpose and triggering conditions before the operational constraints, and every clause carries actionable information. It is dense and slightly long for a two-parameter tool, but there is no filler to cut.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

All the operational knowledge an agent needs to call this successfully — when to fire, how long the payload may be, what happens on overflow, and the formatting expectation — is present. An output schema exists, so the description rightly omits return-value detail.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate and largely does: it explains the message length ceiling, the preferred internal structure (status line, bullets, ask last), and that embed=True yields a rich card versus plain markdown. The only gap is that it doesn't map these constraints back to the named parameter explicitly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Send one notification to the human's Discord whenever their attention is needed.' It also enumerates the triggering conditions (blocked, decision needed, finished, user requested), so an agent knows exactly what this tool is for without any sibling ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly lists when to use it (blocked, missing info, question/warning, important mid-task event, completion, user ping request) and gives the key negative constraint: 'One message per event — do not spam the user.' This is unusually complete routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 1 tool updatev0.1.0
    • First observedsend

TDQS

A4.6/5.0

Scored across 1 tool

Disambiguation5/5

There is only one tool, so there is no possibility of confusion or misselection between tools. Its purpose (send a notification to the human) is stated unambiguously.

Naming Consistency5/5

A single tool named 'send' is a clear, conventional verb. With only one tool there is no inconsistent pattern to violate.

Tool Count4/5

For a narrowly scoped server whose sole job is pinging a human, one tool is the right shape rather than a thin surface. It is minimal but not under-built for the stated purpose.

Completeness4/5

The send tool fully covers the core lifecycle of a fire-and-forget notification (status, ask, formatting, length limits), and no create/update/delete cycle is needed. Minor gaps exist, such as no channel configuration or acknowledgement/read-status retrieval.

Maintenance

ActivityMaintained
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables Claude Code to send notifications to Discord channels via webhooks when tasks complete, errors occur, or user intervention is needed. Deployed serverlessly on Cloudflare Workers with support for rich message formatting and embeds.
    8
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables LLMs to send messages and rich embeds to Discord via webhooks, supporting plain text messages, formatted embeds with images and fields, and customizable webhook appearance for AI-powered Discord notifications and integrations.
    8 npm
    MIT
  • F
    license
    Not graded
    quality
    Not graded
    maintenance
    Enables AI models to send plain text messages, formatted release announcements, and teaser previews to Discord channels using webhooks. It provides secure local webhook management and supports rich embeds with customizable styles for automated notifications.
    153 npm
    -