Server data from the Official MCP Registry
MCP server for self-hosted Gotify push notifications and message management.
MCP server for self-hosted Gotify push notifications and message management.
Valid MCP server (0 strong, 4 medium validity signals). No known CVEs in dependencies. Imported from the Official MCP Registry. Trust signals: trusted author (6/6 approved). 1 finding(s) downgraded by scanner intelligence.
4 files analyzed · 1 issue found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
This plugin requests these system permissions. Most are normal for its category.
Set these up before or after installing:
Environment variable: GOTIFY_URL
Environment variable: GOTIFY_APP_TOKEN
Environment variable: GOTIFY_CLIENT_TOKEN
Environment variable: GOTIFY_MCP_TRANSPORT
Add this to your MCP configuration file:
{
"mcpServers": {
"tv-tootie-gotify-mcp": {
"env": {
"GOTIFY_URL": "your-gotify-url-here",
"GOTIFY_APP_TOKEN": "your-gotify-app-token-here",
"GOTIFY_CLIENT_TOKEN": "your-gotify-client-token-here",
"GOTIFY_MCP_TRANSPORT": "your-gotify-mcp-transport-here"
},
"args": [
"gotify-mcp"
],
"command": "uvx"
}
}
}From the project's GitHub README.
MCP server for self-hosted Gotify. Exposes a unified gotify action router and a gotify_help companion tool for sending notifications and managing Gotify messages, applications, clients, and account metadata.
Two MCP tools are exposed:
| Tool | Purpose |
|---|---|
gotify | Unified action router for all Gotify operations |
gotify_help | Returns markdown documentation for all actions and parameters |
The server supports HTTP (default) and stdio transports. HTTP transport requires bearer authentication via GOTIFY_MCP_TOKEN.
gotify_mcp/server.py: FastMCP server, action router, and BearerAuth middlewaregotify_mcp/services/gotify.py: Async HTTP client for the Gotify REST APIskills/gotify/SKILL.md: Client-facing skill documentationdocs/gotify-api.json: Bundled upstream Gotify API reference.claude-plugin/plugin.json, .codex-plugin/plugin.json, gemini-extension.json: Client manifestsdocker-compose.yml, Dockerfile, entrypoint.sh: Container deploymentscripts/: Smoke tests and contract checksgotifySingle entry point for all Gotify operations. Select the operation with the action parameter.
gotify(action="send_message", app_token="AbCdEf", message="Build finished", priority=5)
gotify_helpReturns the full action reference as Markdown. Call this to discover available actions.
gotify_help()
send_messageSend a push notification. Requires an app_token — this is the per-application token, not the client token.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
app_token | string | yes | — | Application token from Gotify UI (Settings > Apps) |
message | string | yes | — | Notification body. Supports Markdown when extras sets contentType. |
title | string | no | — | Notification title |
priority | integer | no | app default | Priority 0–10. See Priority Levels below. |
extras | dict | no | — | Extended metadata. See Extras Structure below. |
Response fields:
| Field | Type | Description |
|---|---|---|
id | integer | Assigned message ID |
appid | integer | Application ID that sent the message |
message | string | Message body |
title | string | Message title |
priority | integer | Effective priority |
date | string | ISO 8601 timestamp |
extras | dict | Extras as submitted |
Example:
gotify(action="send_message",
app_token="AbCdEf",
title="Deployment done",
message="## Summary\n- All steps complete\n- Ready for review",
priority=7,
extras={"client::display": {"contentType": "text/markdown"}})
list_messagesList messages with pagination and optional filtering.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
app_id | integer | no | — | Filter to messages from one application |
offset | integer | no | 0 | Cursor offset (message ID) — items before this ID are skipped |
limit | integer | no | 50 | Maximum number of messages to return |
sort_by | string | no | "id" | Field to sort by. Valid values: id, date, priority |
sort_order | string | no | "desc" | "asc" or "desc" |
query | string | no | "" | Case-insensitive substring filter applied to title and message body |
Response fields:
| Field | Type | Description |
|---|---|---|
items | array | Array of message objects (same shape as send_message response) |
total | integer | Total messages before pagination |
limit | integer | Limit used |
offset | integer | Offset used |
has_more | boolean | Whether more pages exist |
Note: Gotify uses cursor-style pagination internally. The offset parameter maps to the since query parameter (a message ID), not a row count.
Example:
gotify(action="list_messages", limit=20, sort_order="desc")
gotify(action="list_messages", app_id=3, query="error", limit=10)
delete_messageDelete a single message by ID. Destructive — requires confirm=True.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
message_id | integer | yes | — | ID of the message to delete |
confirm | boolean | yes | False | Must be True to proceed |
Example:
gotify(action="delete_message", message_id=42, confirm=True)
delete_all_messagesDelete all messages across all applications. Destructive — requires confirm=True.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
confirm | boolean | yes | False | Must be True to proceed |
Example:
gotify(action="delete_all_messages", confirm=True)
list_applicationsList all applications registered on the Gotify server.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
offset | integer | no | 0 | Number of items to skip |
limit | integer | no | 50 | Maximum items to return |
query | string | no | "" | Case-insensitive substring filter on application name |
Response fields:
| Field | Type | Description |
|---|---|---|
items | array | Array of application objects |
total | integer | Total applications before pagination |
limit | integer | Limit used |
offset | integer | Offset used |
has_more | boolean | Whether more pages exist |
Each application object contains:
| Field | Type | Description |
|---|---|---|
id | integer | Application ID |
token | string | Application token (use for send_message) |
name | string | Application name |
description | string | Application description |
defaultPriority | integer | Default message priority |
image | string | Path to application image |
internal | boolean | Whether this is an internal application |
Example:
gotify(action="list_applications")
gotify(action="list_applications", query="homelab")
create_applicationCreate a new Gotify application.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | yes | — | Application name |
description | string | no | — | Application description |
default_priority | integer | no | — | Default priority for messages from this app (0–10) |
Returns the created application object.
Example:
gotify(action="create_application",
name="homelab-alerts",
description="Claude Code homelab notifications",
default_priority=5)
update_applicationUpdate an existing application. Provide at least one of name, description, or default_priority.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
app_id | integer | yes | — | ID of the application to update |
name | string | no | — | New application name |
description | string | no | — | New description |
default_priority | integer | no | — | New default priority (0–10) |
Returns the updated application object.
Example:
gotify(action="update_application", app_id=3, name="homelab-alerts-v2", default_priority=7)
delete_applicationDelete an application and all its messages. Destructive — requires confirm=True.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
app_id | integer | yes | — | ID of the application to delete |
confirm | boolean | yes | False | Must be True to proceed |
Example:
gotify(action="delete_application", app_id=3, confirm=True)
list_clientsList all registered Gotify clients. Requires GOTIFY_CLIENT_TOKEN.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
offset | integer | no | 0 | Number of items to skip |
limit | integer | no | 50 | Maximum items to return |
query | string | no | "" | Case-insensitive substring filter on client name |
Response has the same pagination shape as list_applications. Each client object contains id, token, and name.
Example:
gotify(action="list_clients")
create_clientCreate a new Gotify client. Returns the client object including its token.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | yes | — | Client name |
Example:
gotify(action="create_client", name="my-phone")
delete_clientDelete a Gotify client. Destructive — requires confirm=True.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
client_id | integer | yes | — | ID of the client to delete |
confirm | boolean | yes | False | Must be True to proceed |
Example:
gotify(action="delete_client", client_id=5, confirm=True)
healthCheck the Gotify server health status. No additional parameters.
Returns a JSON object with health fields from the upstream Gotify /health endpoint. Note: this MCP tool call requires bearer authentication. The raw HTTP /health endpoint on the MCP server is unauthenticated.
Example:
gotify(action="health")
versionGet the Gotify server version. No additional parameters. No authentication required on the upstream call.
Example:
gotify(action="version")
current_userGet the current authenticated user's account information. Requires GOTIFY_CLIENT_TOKEN.
No additional parameters. Returns the user object with id, name, and admin fields.
Example:
gotify(action="current_user")
Gotify uses two separate token types. Using the wrong type will produce a 401 error.
| Token | Source | Used for |
|---|---|---|
| App token | Gotify UI: Settings > Apps > Create Application | send_message only — passed per call as app_token |
| Client token | Gotify UI: Settings > Clients > Create Client | All management actions: list/delete messages, list/create/delete apps and clients, current_user |
The MCP server reads GOTIFY_CLIENT_TOKEN from the environment and uses it automatically for management actions. You never pass it explicitly to the tool.
The app_token for send_message is always passed explicitly per call — it is not read from the server environment.
The priority field is an integer from 0 to 10. Gotify clients interpret priority ranges as follows:
| Range | Level | Recommended use |
|---|---|---|
| 0–3 | Low | Informational, FYI messages |
| 4–7 | Normal | Task updates, completions, standard alerts |
| 8–10 | High | Blocked states, errors, urgent alerts |
If priority is omitted from send_message, the application's defaultPriority is used. If the application has no default, Gotify falls back to 0.
The extras field in send_message is a free-form dict passed to the Gotify API. The most common use is enabling Markdown rendering:
extras={"client::display": {"contentType": "text/markdown"}}
Other known namespaces from the upstream Gotify extras specification:
| Key | Value type | Description |
|---|---|---|
client::display | dict | Display hints for Gotify clients |
client::display.contentType | string | "text/plain" (default) or "text/markdown" |
client::notification | dict | Platform-specific notification overrides |
Any key/value pairs are accepted — the server passes them through as-is.
Four actions are gated behind a confirmation check:
delete_messagedelete_all_messagesdelete_applicationdelete_clientWithout confirm=True, the server returns:
{"error": "Destructive operation. Pass confirm=True to proceed."}
To bypass the gate server-wide, set either environment variable:
ALLOW_DESTRUCTIVE=true # skip confirm check
ALLOW_YOLO=true # identical effect
These env vars are intended for automated environments where interactive confirmation is not possible.
List actions (list_messages, list_applications, list_clients) share a common pagination interface:
| Parameter | Type | Default | Notes |
|---|---|---|---|
offset | integer | 0 | Items to skip. For list_messages, maps to the since cursor (a message ID). For list_applications and list_clients, applied client-side as a row offset. |
limit | integer | 50 | Maximum items per page |
sort_by | string | "id" | list_messages only. Field to sort by: id, date, priority. Not applied for apps or clients. |
sort_order | string | "desc" | list_messages only. "asc" or "desc". |
query | string | "" | Substring filter. Matches title and body for messages; name for apps and clients. Case-insensitive. |
All list responses include total, limit, offset, and has_more alongside the items array.
All errors return a JSON object with these fields:
| Field | Type | Description |
|---|---|---|
error | string | Short error identifier |
errorCode | integer | HTTP status code or 500 for network errors |
errorDescription | string | Human-readable explanation |
Common errors:
| error | errorCode | Cause |
|---|---|---|
Unauthorized | 401 | Wrong or missing token type for the operation |
HTTP 403 | 403 | Token valid but operation not permitted for this user |
HTTP 404 | 404 | Message, application, or client ID does not exist |
NoUpdateFields | 400 | update_application called with no fields to update |
RequestError | 500 | Network failure reaching the Gotify server |
No token provided | 401 | Neither app_token nor GOTIFY_CLIENT_TOKEN is set |
Responses are truncated at 512 KB. Truncated responses include ... [truncated] at the end.
Install as a Claude Code plugin. You will be prompted for:
The plugin uses stdio transport with ${userConfig.*} interpolation — no .env file needed.
cp .env.example .env
chmod 600 .env
# Edit .env with your credentials
docker compose up -d
uv sync --dev
uv run gotify-mcp-server
Two deployment paths are supported:
| Path | Transport | Credentials | Auth |
|---|---|---|---|
| Plugin (stdio) | stdio | userConfig in plugin settings | None |
| Docker (HTTP) | http | .env file | Bearer token |
See docs/CONFIG.md for the full environment variable reference.
When running inside Docker, localhost and 127.0.0.1 in GOTIFY_URL are automatically rewritten to host.docker.internal so the container can reach a host-side Gotify server.
gotify(action="send_message",
app_token="AbCdEf",
title="Build finished",
message="All tests passed.",
priority=5)
gotify(action="send_message",
app_token="AbCdEf",
title="Deploy complete",
message="## Status\n- All steps done\n- Ready for review",
priority=7,
extras={"client::display": {"contentType": "text/markdown"}})
# First page
gotify(action="list_messages", limit=25, offset=0)
# Next page (use the ID of the last message as offset)
gotify(action="list_messages", limit=25, offset=99)
gotify(action="list_messages", query="error", limit=20)
gotify(action="list_messages", app_id=3, limit=50)
# List all applications
gotify(action="list_applications")
# Create
gotify(action="create_application",
name="homelab-alerts",
description="Automated notifications",
default_priority=5)
# Update
gotify(action="update_application", app_id=3, default_priority=7)
# Delete (destructive)
gotify(action="delete_application", app_id=3, confirm=True)
# List all clients
gotify(action="list_clients")
# Create
gotify(action="create_client", name="my-phone")
# Delete (destructive)
gotify(action="delete_client", client_id=5, confirm=True)
gotify(action="health")
gotify(action="version")
gotify(action="current_user")
When MCP tools are unavailable, use direct HTTP calls. App tokens go to /message, client tokens go to management endpoints.
# Send a notification
curl -s -X POST "$GOTIFY_URL/message" \
-H "X-Gotify-Key: $GOTIFY_APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"Done","message":"All steps complete","priority":7}'
# List messages
curl -s "$GOTIFY_URL/message" \
-H "X-Gotify-Key: $GOTIFY_CLIENT_TOKEN"
# List applications
curl -s "$GOTIFY_URL/application" \
-H "X-Gotify-Key: $GOTIFY_CLIENT_TOKEN"
# Health (no auth)
curl -s "$GOTIFY_URL/health"
just setup
This copies .env.example to .env (if not already present) and installs all dependencies.
just dev # Run the server locally (uv run python -m gotify_mcp.server)
just lint # Run ruff check
just fmt # Run ruff format
just typecheck # Run ty check
just test # Run pytest
just build # Build Docker image
just up # Start via docker compose
just down # Stop docker compose
just restart # Restart docker compose
just logs # Follow docker compose logs
just health # curl http://localhost:9158/health
just test-live # Run live integration tests (requires running server)
just gen-token # Generate a random bearer token
just clean # Remove build artifacts
Run before committing:
just lint
just typecheck
just test
Live verification (requires a running server and Gotify instance):
just test-live
The MCP server exposes an unauthenticated HTTP health endpoint:
GET http://localhost:9158/health
This proxies through to the Gotify server's /health and returns:
{"status": "ok", "gotify": {...}}
Or on failure:
{"status": "error", "reason": "..."}
The server writes rotating logs to logs/gotify_mcp.log (max 5 MB, 3 backups). Log level is controlled by GOTIFY_LOG_LEVEL.
| Plugin | Category | Description |
|---|---|---|
| homelab-core | core | Core agents, commands, skills, and setup/health workflows for homelab management. |
| overseerr-mcp | media | Search movies and TV shows, submit requests, and monitor failed requests via Overseerr. |
| unraid-mcp | infrastructure | Query, monitor, and manage Unraid servers: Docker, VMs, array, parity, and live telemetry. |
| unifi-mcp | infrastructure | Monitor and manage UniFi devices, clients, firewall rules, and network health. |
| swag-mcp | infrastructure | Create, edit, and manage SWAG nginx reverse proxy configurations. |
| synapse-mcp | infrastructure | Docker management (Flux) and SSH remote operations (Scout) across homelab hosts. |
| arcane-mcp | infrastructure | Manage Docker environments, containers, images, volumes, networks, and GitOps via Arcane. |
| syslog-mcp | infrastructure | Receive, index, and search syslog streams from all homelab hosts via SQLite FTS5. |
| plugin-lab | dev-tools | Scaffold, review, align, and deploy homelab MCP plugins with agents and canonical templates. |
MIT
Be the first to review this server!
by Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.
by mcp-marketplace · Developer Tools
Create, build, and publish Python MCP servers to PyPI — conversationally.
by Microsoft · Content & Media
Convert files (PDF, Word, Excel, images, audio) to Markdown for LLM consumption
by mcp-marketplace · Developer Tools
Scaffold, build, and publish TypeScript MCP servers to npm — conversationally
by mcp-marketplace · Finance
Free stock data and market news for any MCP-compatible AI assistant.
by Taylorwilsdon · Productivity
Control Gmail, Calendar, Docs, Sheets, Drive, and more from your AI