🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

gotify-mcp

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gotify-mcp

MCP server for Gotify push notifications

pipPyPI
Version
0.3.2
Weekly downloads
34
-85.89%
Maintainers
1
Weekly downloads
 

Gotify MCP

PyPI ghcr.io

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.

Overview

Two MCP tools are exposed:

ToolPurpose
gotifyUnified action router for all Gotify operations
gotify_helpReturns markdown documentation for all actions and parameters

The server supports HTTP (default) and stdio transports. HTTP transport requires bearer authentication via GOTIFY_MCP_TOKEN.

What this repository ships

  • gotify_mcp/server.py: FastMCP server, action router, and BearerAuth middleware
  • gotify_mcp/services/gotify.py: Async HTTP client for the Gotify REST API
  • skills/gotify/SKILL.md: Client-facing skill documentation
  • docs/gotify-api.json: Bundled upstream Gotify API reference
  • .claude-plugin/plugin.json, .codex-plugin/plugin.json, gemini-extension.json: Client manifests
  • docker-compose.yml, Dockerfile, entrypoint.sh: Container deployment
  • scripts/: Smoke tests and contract checks

Tools

gotify

Single 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_help

Returns the full action reference as Markdown. Call this to discover available actions.

gotify_help()

Actions

send_message

Send a push notification. Requires an app_token — this is the per-application token, not the client token.

ParameterTypeRequiredDefaultDescription
app_tokenstringyesApplication token from Gotify UI (Settings > Apps)
messagestringyesNotification body. Supports Markdown when extras sets contentType.
titlestringnoNotification title
priorityintegernoapp defaultPriority 0–10. See Priority Levels below.
extrasdictnoExtended metadata. See Extras Structure below.

Response fields:

FieldTypeDescription
idintegerAssigned message ID
appidintegerApplication ID that sent the message
messagestringMessage body
titlestringMessage title
priorityintegerEffective priority
datestringISO 8601 timestamp
extrasdictExtras 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_messages

List messages with pagination and optional filtering.

ParameterTypeRequiredDefaultDescription
app_idintegernoFilter to messages from one application
offsetintegerno0Cursor offset (message ID) — items before this ID are skipped
limitintegerno50Maximum number of messages to return
sort_bystringno"id"Field to sort by. Valid values: id, date, priority
sort_orderstringno"desc""asc" or "desc"
querystringno""Case-insensitive substring filter applied to title and message body

Response fields:

FieldTypeDescription
itemsarrayArray of message objects (same shape as send_message response)
totalintegerTotal messages before pagination
limitintegerLimit used
offsetintegerOffset used
has_morebooleanWhether 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_message

Delete a single message by ID. Destructive — requires confirm=True.

ParameterTypeRequiredDefaultDescription
message_idintegeryesID of the message to delete
confirmbooleanyesFalseMust be True to proceed

Example:

gotify(action="delete_message", message_id=42, confirm=True)

delete_all_messages

Delete all messages across all applications. Destructive — requires confirm=True.

ParameterTypeRequiredDefaultDescription
confirmbooleanyesFalseMust be True to proceed

Example:

gotify(action="delete_all_messages", confirm=True)

list_applications

List all applications registered on the Gotify server.

ParameterTypeRequiredDefaultDescription
offsetintegerno0Number of items to skip
limitintegerno50Maximum items to return
querystringno""Case-insensitive substring filter on application name

Response fields:

FieldTypeDescription
itemsarrayArray of application objects
totalintegerTotal applications before pagination
limitintegerLimit used
offsetintegerOffset used
has_morebooleanWhether more pages exist

Each application object contains:

FieldTypeDescription
idintegerApplication ID
tokenstringApplication token (use for send_message)
namestringApplication name
descriptionstringApplication description
defaultPriorityintegerDefault message priority
imagestringPath to application image
internalbooleanWhether this is an internal application

Example:

gotify(action="list_applications")
gotify(action="list_applications", query="homelab")

create_application

Create a new Gotify application.

ParameterTypeRequiredDefaultDescription
namestringyesApplication name
descriptionstringnoApplication description
default_priorityintegernoDefault 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_application

Update an existing application. Provide at least one of name, description, or default_priority.

ParameterTypeRequiredDefaultDescription
app_idintegeryesID of the application to update
namestringnoNew application name
descriptionstringnoNew description
default_priorityintegernoNew 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_application

Delete an application and all its messages. Destructive — requires confirm=True.

ParameterTypeRequiredDefaultDescription
app_idintegeryesID of the application to delete
confirmbooleanyesFalseMust be True to proceed

Example:

gotify(action="delete_application", app_id=3, confirm=True)

list_clients

List all registered Gotify clients. Requires GOTIFY_CLIENT_TOKEN.

ParameterTypeRequiredDefaultDescription
offsetintegerno0Number of items to skip
limitintegerno50Maximum items to return
querystringno""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_client

Create a new Gotify client. Returns the client object including its token.

ParameterTypeRequiredDefaultDescription
namestringyesClient name

Example:

gotify(action="create_client", name="my-phone")

delete_client

Delete a Gotify client. Destructive — requires confirm=True.

ParameterTypeRequiredDefaultDescription
client_idintegeryesID of the client to delete
confirmbooleanyesFalseMust be True to proceed

Example:

gotify(action="delete_client", client_id=5, confirm=True)

health

Check 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")

version

Get the Gotify server version. No additional parameters. No authentication required on the upstream call.

Example:

gotify(action="version")

current_user

Get 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")

Token Types

Gotify uses two separate token types. Using the wrong type will produce a 401 error.

TokenSourceUsed for
App tokenGotify UI: Settings > Apps > Create Applicationsend_message only — passed per call as app_token
Client tokenGotify UI: Settings > Clients > Create ClientAll 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.

Priority Levels

The priority field is an integer from 0 to 10. Gotify clients interpret priority ranges as follows:

RangeLevelRecommended use
0–3LowInformational, FYI messages
4–7NormalTask updates, completions, standard alerts
8–10HighBlocked 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.

Extras Structure

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:

KeyValue typeDescription
client::displaydictDisplay hints for Gotify clients
client::display.contentTypestring"text/plain" (default) or "text/markdown"
client::notificationdictPlatform-specific notification overrides

Any key/value pairs are accepted — the server passes them through as-is.

Destructive Operations

Four actions are gated behind a confirmation check:

  • delete_message
  • delete_all_messages
  • delete_application
  • delete_client

Without 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.

Pagination

List actions (list_messages, list_applications, list_clients) share a common pagination interface:

ParameterTypeDefaultNotes
offsetinteger0Items 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.
limitinteger50Maximum items per page
sort_bystring"id"list_messages only. Field to sort by: id, date, priority. Not applied for apps or clients.
sort_orderstring"desc"list_messages only. "asc" or "desc".
querystring""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.

Error Handling

All errors return a JSON object with these fields:

FieldTypeDescription
errorstringShort error identifier
errorCodeintegerHTTP status code or 500 for network errors
errorDescriptionstringHuman-readable explanation

Common errors:

errorerrorCodeCause
Unauthorized401Wrong or missing token type for the operation
HTTP 403403Token valid but operation not permitted for this user
HTTP 404404Message, application, or client ID does not exist
NoUpdateFields400update_application called with no fields to update
RequestError500Network failure reaching the Gotify server
No token provided401Neither app_token nor GOTIFY_CLIENT_TOKEN is set

Responses are truncated at 512 KB. Truncated responses include ... [truncated] at the end.

Installation

Marketplace

/plugin marketplace add jmagar/claude-homelab
/plugin install gotify-mcp @jmagar-claude-homelab

Local development

uv sync --dev
uv run gotify-mcp-server

Direct module invocation:

uv run python -m gotify_mcp.server

Docker

just up

Or manually:

docker compose up -d

Configuration

Copy .env.example to .env and fill in the required values:

cp .env.example .env

Environment variables

VariableRequiredDefaultDescription
GOTIFY_URLyesBase URL of your Gotify server (no trailing slash). Server exits at startup if unset.
GOTIFY_CLIENT_TOKENyes*Client token for management operations. Without this, all management actions fail.
GOTIFY_APP_TOKENnoApp token used in HTTP fallback examples. The MCP tool requires app_token per call.
GOTIFY_MCP_HOSTno0.0.0.0Interface for the MCP HTTP server to bind to
GOTIFY_MCP_PORTno9158Port for the MCP HTTP server
GOTIFY_MCP_TRANSPORTnohttpTransport mode: http or stdio
GOTIFY_MCP_TOKENyes**Bearer token for MCP server authentication. Generate with openssl rand -hex 32. Required when transport is http and GOTIFY_MCP_NO_AUTH is not set.
GOTIFY_MCP_NO_AUTHnofalseSet true to disable bearer auth. Appropriate only behind a trusted reverse proxy.
GOTIFY_LOG_LEVELnoINFOLog level: DEBUG, INFO, WARNING, ERROR, CRITICAL
ALLOW_DESTRUCTIVEnofalseSet true to skip confirm=True requirement for destructive actions
ALLOW_YOLOnofalseIdentical to ALLOW_DESTRUCTIVE
PUIDno1000User ID for container process
PGIDno1000Group ID for container process

*GOTIFY_CLIENT_TOKEN is required for management actions. Without it, a warning is logged at startup and management actions return 401.

**GOTIFY_MCP_TOKEN is required when GOTIFY_MCP_TRANSPORT=http and GOTIFY_MCP_NO_AUTH=false. The server exits at startup if neither is set.

Docker URL rewriting

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.

Usage examples

Send a plain text notification

gotify(action="send_message",
       app_token="AbCdEf",
       title="Build finished",
       message="All tests passed.",
       priority=5)

Send a Markdown notification

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"}})

Page through messages

# 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)

Filter messages by text

gotify(action="list_messages", query="error", limit=20)

Filter messages from one application

gotify(action="list_messages", app_id=3, limit=50)

Manage applications

# 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)

Manage clients

# 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)

Server info

gotify(action="health")
gotify(action="version")
gotify(action="current_user")

HTTP fallback

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"

Development

Setup

just setup

This copies .env.example to .env (if not already present) and installs all dependencies.

Commands

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

Verification

Run before committing:

just lint
just typecheck
just test

Live verification (requires a running server and Gotify instance):

just test-live

Server health endpoint

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": "..."}

Logs

The server writes rotating logs to logs/gotify_mcp.log (max 5 MB, 3 backups). Log level is controlled by GOTIFY_LOG_LEVEL.

PluginCategoryDescription
homelab-corecoreCore agents, commands, skills, and setup/health workflows for homelab management.
overseerr-mcpmediaSearch movies and TV shows, submit requests, and monitor failed requests via Overseerr.
unraid-mcpinfrastructureQuery, monitor, and manage Unraid servers: Docker, VMs, array, parity, and live telemetry.
unifi-mcpinfrastructureMonitor and manage UniFi devices, clients, firewall rules, and network health.
swag-mcpinfrastructureCreate, edit, and manage SWAG nginx reverse proxy configurations.
synapse-mcpinfrastructureDocker management (Flux) and SSH remote operations (Scout) across homelab hosts.
arcane-mcpinfrastructureManage Docker environments, containers, images, volumes, networks, and GitOps via Arcane.
syslog-mcpinfrastructureReceive, index, and search syslog streams from all homelab hosts via SQLite FTS5.
plugin-labdev-toolsScaffold, review, align, and deploy homelab MCP plugins with agents and canonical templates.
axonresearchSelf-hosted web crawl, ingest, embed, and RAG pipeline with MCP tooling.

License

MIT

FAQs

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts