MCP client that lets your agents play notification sounds and show desktop toasts
sound-mcp
A small FastMCP server that lets the agent play a notification sound, and optionally pop a desktop toast, when something finishes. Useful for "poll X until Y, then ping me" workflows.
Tools
list_sounds(): show every available sound name and the current default.play_sound(name=None): play a registered sound, an absolute file path, or the default.set_default_sound(name_or_path): persist a new default (registered name or absolute path) to~/.config/sound-mcp/default. Survives restarts. Overridden at runtime bySOUND_MCP_DEFAULTif it is set inmcp.json.notify(message, title="Claude", sound=None, urgency="normal", expire_ms=0): desktop toast + sound.urgency=critical: makes the toast sticky on most desktops.
Requirements
Linux with paplay (PulseAudio/PipeWire) and notify-send (libnotify-bin).
Builtin sounds come from sound-theme-freedesktop, preinstalled on Ubuntu.
You only need uv and Python ≥ 3.11.
Quick start
Claude Code
claude mcp add sound-mcp -- uvx --from git+https://github.com/giuliocapecchi/sound-mcp sound-mcp
Other MCP clients (Claude Desktop, Codex, OpenCode, …)
Add this block to your client's MCP config file:
{
"mcpServers": {
"sound-mcp": {
"command": "uvx",
"args": ["--from", "git+https://github.com/giuliocapecchi/sound-mcp", "sound-mcp"]
}
}
}
Common config locations:
| Client | Config file |
| --------------- | ---------------------------- |
| Claude Desktop | claude_desktop_config.json |
| Codex (OpenAI) | ~/.codex/config.json |
| OpenCode | opencode.json |
Configuration
All settings are read from environment variables, so you set them in the env
block of your mcp.json (or equivalent):
{
"mcpServers": {
"sound-mcp": {
"command": "uvx",
"args": ["--from", "git+https://github.com/giuliocapecchi/sound-mcp", "sound-mcp"],
"env": {
"SOUND_MCP_DEFAULT": "warning",
"SOUND_MCP_SOUNDS_DIR": "/home/you/.config/sound-mcp/sounds"
}
}
}
}
| Variable | Default | Purpose |
| ---------------------- | ---------------------------------- | ------------------------------------------------------------- |
| SOUND_MCP_DEFAULT | warning | Sound played when play_sound/notify is called with no name. |
| SOUND_MCP_SOUNDS_DIR | ~/.config/sound-mcp/sounds | Directory scanned for user sound files. |
Custom sounds
Builtin names: complete, bell, warning, error, alarm.
Drop audio files (.oga, .ogg, .wav, .mp3, .flac) into your sounds
directory and each becomes a sound keyed by its filename stem. For example
tada.wav → play_sound("tada"). User files override builtins on name collision.
You can also pass an absolute path directly: play_sound("/tmp/horn.wav").
Example prompt
Poll
tailscale statusevery 10 seconds. When nodemyservershows as online, call thenotifytool withtitle="Tailscale"andmessage="myserver is back".
Local development
git clone https://github.com/giuliocapecchi/sound-mcp
cd sound-mcp
uv venv && uv pip install -e .
uv run fastmcp dev src/sound_mcp/server.py # opens MCP Inspector
License
MIT.