notify-human-mcp
Allows sending messages to a Discord webhook, delivering notifications, questions, blockers, decisions, or task updates from the LLM to the user via Discord; can post messages as markdown text or rich embed cards.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@notify-human-mcpnotify me on Discord that you're blocked waiting for my approval"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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 |
| prose mode: | Posts to your Discord webhook. Prose: |
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-mcpRelated 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 |
| yes | Your Discord webhook URL. Each machine/user gets its own. |
| no | Instructions file: |
| 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 toolsendA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| embed | No | ||
| message | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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 tool update
v0.1.0- First observed
send
TDQS
Scored across 1 tool
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.
A single tool named 'send' is a clear, conventional verb. With only one tool there is no inconsistent pattern to violate.
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.
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
Related MCP Connectors
Give any AI agent a way to ask a person — for approval, a decision, an answer or a review.
Let your AI agent notify you by email, Slack, Discord, or webhook. One tool: send_notification.
Human approvals, notifications, inbound webhooks, wake-ups for headless agents. Free trial: /try
Human-in-the-loop for AI coding agents — ask questions, get approvals via Slack.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables 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.8MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to send messages to human users via chat platforms (currently Discord) and optionally wait for human responses, facilitating human-in-the-loop interactions.MIT
- AlicenseNot gradedqualityDmaintenanceEnables 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 npmMIT
- FlicenseNot gradedqualityNot gradedmaintenanceEnables 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-