ntfy-mcp-server 1.0.4 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/CLAUDE.md +409 -0
  2. package/Dockerfile +98 -0
  3. package/README.md +167 -393
  4. package/changelog/1.0.x/1.0.0.md +13 -0
  5. package/changelog/1.0.x/1.0.1.md +11 -0
  6. package/changelog/1.0.x/1.0.2.md +12 -0
  7. package/changelog/1.0.x/1.0.3.md +17 -0
  8. package/changelog/1.0.x/1.0.4.md +12 -0
  9. package/changelog/1.0.x/1.0.6.md +22 -0
  10. package/changelog/2.0.x/2.0.0.md +57 -0
  11. package/changelog/template.md +93 -0
  12. package/dist/config/server-config.d.ts +41 -0
  13. package/dist/config/server-config.d.ts.map +1 -0
  14. package/dist/config/server-config.js +189 -0
  15. package/dist/config/server-config.js.map +1 -0
  16. package/dist/index.d.ts +8 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +22 -104
  19. package/dist/index.js.map +1 -0
  20. package/dist/mcp-server/resources/definitions/ntfy-topic.resource.d.ts +12 -0
  21. package/dist/mcp-server/resources/definitions/ntfy-topic.resource.d.ts.map +1 -0
  22. package/dist/mcp-server/resources/definitions/ntfy-topic.resource.js +58 -0
  23. package/dist/mcp-server/resources/definitions/ntfy-topic.resource.js.map +1 -0
  24. package/dist/mcp-server/tools/definitions/ntfy-fetch-messages.tool.d.ts +101 -0
  25. package/dist/mcp-server/tools/definitions/ntfy-fetch-messages.tool.d.ts.map +1 -0
  26. package/dist/mcp-server/tools/definitions/ntfy-fetch-messages.tool.js +408 -0
  27. package/dist/mcp-server/tools/definitions/ntfy-fetch-messages.tool.js.map +1 -0
  28. package/dist/mcp-server/tools/definitions/ntfy-manage-message.tool.d.ts +44 -0
  29. package/dist/mcp-server/tools/definitions/ntfy-manage-message.tool.d.ts.map +1 -0
  30. package/dist/mcp-server/tools/definitions/ntfy-manage-message.tool.js +133 -0
  31. package/dist/mcp-server/tools/definitions/ntfy-manage-message.tool.js.map +1 -0
  32. package/dist/mcp-server/tools/definitions/ntfy-publish-message.tool.d.ts +125 -0
  33. package/dist/mcp-server/tools/definitions/ntfy-publish-message.tool.d.ts.map +1 -0
  34. package/dist/mcp-server/tools/definitions/ntfy-publish-message.tool.js +411 -0
  35. package/dist/mcp-server/tools/definitions/ntfy-publish-message.tool.js.map +1 -0
  36. package/dist/mcp-server/tools/definitions/ntfy-search-emoji-tags.tool.d.ts +20 -0
  37. package/dist/mcp-server/tools/definitions/ntfy-search-emoji-tags.tool.d.ts.map +1 -0
  38. package/dist/mcp-server/tools/definitions/ntfy-search-emoji-tags.tool.js +69 -0
  39. package/dist/mcp-server/tools/definitions/ntfy-search-emoji-tags.tool.js.map +1 -0
  40. package/dist/services/emoji-tags/data.generated.d.ts +8 -0
  41. package/dist/services/emoji-tags/data.generated.d.ts.map +1 -0
  42. package/dist/services/emoji-tags/data.generated.js +1821 -0
  43. package/dist/services/emoji-tags/data.generated.js.map +1 -0
  44. package/dist/services/emoji-tags/emoji-tag-service.d.ts +28 -0
  45. package/dist/services/emoji-tags/emoji-tag-service.d.ts.map +1 -0
  46. package/dist/services/emoji-tags/emoji-tag-service.js +50 -0
  47. package/dist/services/emoji-tags/emoji-tag-service.js.map +1 -0
  48. package/dist/services/ntfy/error-classifier.d.ts +31 -0
  49. package/dist/services/ntfy/error-classifier.d.ts.map +1 -0
  50. package/dist/services/ntfy/error-classifier.js +65 -0
  51. package/dist/services/ntfy/error-classifier.js.map +1 -0
  52. package/dist/services/ntfy/ntfy-service.d.ts +42 -0
  53. package/dist/services/ntfy/ntfy-service.d.ts.map +1 -0
  54. package/dist/services/ntfy/ntfy-service.js +213 -0
  55. package/dist/services/ntfy/ntfy-service.js.map +1 -0
  56. package/dist/services/ntfy/types.d.ts +108 -138
  57. package/dist/services/ntfy/types.d.ts.map +1 -0
  58. package/dist/services/ntfy/types.js +6 -1
  59. package/dist/services/ntfy/types.js.map +1 -0
  60. package/package.json +76 -38
  61. package/server.json +224 -0
  62. package/dist/config/index.d.ts +0 -23
  63. package/dist/config/index.js +0 -111
  64. package/dist/mcp-server/resources/ntfyResource/getNtfyTopic.d.ts +0 -2
  65. package/dist/mcp-server/resources/ntfyResource/getNtfyTopic.js +0 -133
  66. package/dist/mcp-server/resources/ntfyResource/index.d.ts +0 -12
  67. package/dist/mcp-server/resources/ntfyResource/index.js +0 -77
  68. package/dist/mcp-server/resources/ntfyResource/types.d.ts +0 -59
  69. package/dist/mcp-server/resources/ntfyResource/types.js +0 -8
  70. package/dist/mcp-server/server.d.ts +0 -40
  71. package/dist/mcp-server/server.js +0 -299
  72. package/dist/mcp-server/tools/ntfyTool/index.d.ts +0 -11
  73. package/dist/mcp-server/tools/ntfyTool/index.js +0 -124
  74. package/dist/mcp-server/tools/ntfyTool/ntfyMessage.d.ts +0 -9
  75. package/dist/mcp-server/tools/ntfyTool/ntfyMessage.js +0 -307
  76. package/dist/mcp-server/tools/ntfyTool/types.d.ts +0 -252
  77. package/dist/mcp-server/tools/ntfyTool/types.js +0 -144
  78. package/dist/mcp-server/utils/registrationHelper.d.ts +0 -48
  79. package/dist/mcp-server/utils/registrationHelper.js +0 -63
  80. package/dist/services/ntfy/constants.d.ts +0 -37
  81. package/dist/services/ntfy/constants.js +0 -37
  82. package/dist/services/ntfy/errors.d.ts +0 -79
  83. package/dist/services/ntfy/errors.js +0 -134
  84. package/dist/services/ntfy/index.d.ts +0 -33
  85. package/dist/services/ntfy/index.js +0 -56
  86. package/dist/services/ntfy/publisher.d.ts +0 -66
  87. package/dist/services/ntfy/publisher.js +0 -229
  88. package/dist/services/ntfy/subscriber.d.ts +0 -81
  89. package/dist/services/ntfy/subscriber.js +0 -502
  90. package/dist/services/ntfy/utils.d.ts +0 -85
  91. package/dist/services/ntfy/utils.js +0 -410
  92. package/dist/types-global/errors.d.ts +0 -35
  93. package/dist/types-global/errors.js +0 -39
  94. package/dist/types-global/mcp.d.ts +0 -30
  95. package/dist/types-global/mcp.js +0 -25
  96. package/dist/types-global/tool.d.ts +0 -44
  97. package/dist/types-global/tool.js +0 -30
  98. package/dist/utils/errorHandler.d.ts +0 -98
  99. package/dist/utils/errorHandler.js +0 -271
  100. package/dist/utils/idGenerator.d.ts +0 -94
  101. package/dist/utils/idGenerator.js +0 -149
  102. package/dist/utils/index.d.ts +0 -13
  103. package/dist/utils/index.js +0 -16
  104. package/dist/utils/logger.d.ts +0 -38
  105. package/dist/utils/logger.js +0 -141
  106. package/dist/utils/rateLimiter.d.ts +0 -115
  107. package/dist/utils/rateLimiter.js +0 -180
  108. package/dist/utils/requestContext.d.ts +0 -68
  109. package/dist/utils/requestContext.js +0 -91
  110. package/dist/utils/sanitization.d.ts +0 -224
  111. package/dist/utils/sanitization.js +0 -367
  112. package/dist/utils/security.d.ts +0 -26
  113. package/dist/utils/security.js +0 -27
package/README.md CHANGED
@@ -1,484 +1,258 @@
1
- # Ntfy MCP Server
2
-
3
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.8.3-blue.svg)](https://www.typescriptlang.org/)
4
- [![Model Context Protocol](https://img.shields.io/badge/MCP-1.10.2-green.svg)](https://modelcontextprotocol.io/)
5
- [![Version](https://img.shields.io/badge/Version-1.0.4-blue.svg)](https://github.com/cyanheads/ntfy-mcp-server/releases)
6
- [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
7
- [![Status](https://img.shields.io/badge/Status-Stable-green.svg)](https://github.com/cyanheads/ntfy-mcp-server)
8
- [![GitHub](https://img.shields.io/github/stars/cyanheads/ntfy-mcp-server?style=social)](https://github.com/cyanheads/ntfy-mcp-server)
9
-
10
- An MCP (Model Context Protocol) server designed to interact with the [ntfy](https://ntfy.sh/) push notification service. It enables LLMs and AI agents to send notifications to your devices with extensive customization options.
11
-
12
- ## Table of Contents
13
-
14
- - [Overview](#overview)
15
- - [Features](#features)
16
- - [Quick Start](#quick-start)
17
- - [Installation](#installation)
18
- - [Configuration](#configuration)
19
- - [Project Structure](#project-structure)
20
- - [Tools](#tools)
21
- - [Resources](#resources)
22
- - [Use Cases](#use-cases)
23
- - [Available Scripts](#available-scripts)
24
- - [Contributing](#contributing)
25
- - [License](#license)
26
-
27
- ## Overview
28
-
29
- This server implements the Model Context Protocol (MCP), enabling standardized communication between LLMs and external systems. Specifically, it provides an interface to the ntfy push notification service.
30
-
31
- [Ntfy](https://ntfy.sh/) is a simple HTTP-based pub-sub notification service that allows you to send notifications to your phone or desktop via simple HTTP requests. With this MCP server, LLM agents like Claude can send notifications to you through ntfy without needing direct HTTP access.
32
-
33
- ```
34
- ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌─────────┐
35
- │ LLM Agent │ ────▶│ Ntfy MCP │ ────▶│ Ntfy │ ────▶│ Your │
36
- │ (Claude) │ │ Server │ │ Service │ │ Devices │
37
- └───────────┘ └───────────┘ └───────────┘ └─────────┘
38
- ```
39
-
40
- ## Features
41
-
42
- - **MCP Server Implementation:** Built using the `@modelcontextprotocol/sdk` for seamless integration with LLM agents.
43
- - **Ntfy Integration:** Provides a tool (`send_ntfy`) to send notifications with support for:
44
- - Message prioritization (1-5 levels)
45
- - Emoji tags
46
- - Clickable actions and buttons
47
- - File attachments
48
- - Delayed delivery
49
- - Markdown formatting
50
- - **Resource Exposure:** Exposes the configured default ntfy topic as an MCP resource.
51
- - **TypeScript:** Modern, type-safe codebase with comprehensive type definitions.
52
- - **Structured Logging:** Uses `winston` and `winston-daily-rotate-file` for detailed and rotatable logs.
53
- - **Configuration Management:** Uses `dotenv` for easy environment-based configuration.
54
- - **Utility Scripts:** Includes scripts for cleaning build artifacts and generating directory structure documentation.
55
- - **Error Handling & Security:** Implements robust error handling, input sanitization (`sanitize-html`), and security filters (`xss-filters`).
56
-
57
- ## Quick Start
1
+ <div align="center">
2
+ <h1>ntfy-mcp-server</h1>
3
+ <p><b>Send, manage, and replay ntfy push notifications via MCP. STDIO or Streamable HTTP.</b>
4
+ <div>4 Tools 1 Resource</div>
5
+ </p>
6
+ </div>
58
7
 
59
- 1. **Prerequisites:**
8
+ <div align="center">
60
9
 
61
- - Node.js (v16+)
62
- - npm or yarn
63
- - An MCP-compatible client (Claude Desktop, Cline, etc.)
10
+ [![npm](https://img.shields.io/npm/v/ntfy-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/ntfy-mcp-server) [![Version](https://img.shields.io/badge/Version-2.0.0-blue.svg?style=flat-square)](./CHANGELOG.md) [![Framework](https://img.shields.io/badge/Built%20on-@cyanheads/mcp--ts--core-259?style=flat-square)](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.29.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/)
64
11
 
65
- 2. **Install and Run:**
12
+ [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![TypeScript](https://img.shields.io/badge/TypeScript-^6.0.3-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.3.11-blueviolet.svg?style=flat-square)](https://bun.sh/)
66
13
 
67
- ```bash
68
- # Option 1: Install via npm
69
- npm install -g ntfy-mcp-server
14
+ </div>
70
15
 
71
- # Option 2: Clone repository and build
72
- git clone https://github.com/cyanheads/ntfy-mcp-server.git
73
- cd ntfy-mcp-server
74
- npm install
75
- npm run build
16
+ ---
76
17
 
77
- # Create .env file (optional but recommended)
78
- cp .env.example .env
79
- # Edit .env to set NTFY_DEFAULT_TOPIC
18
+ ## Tools
80
19
 
81
- # Start the server
82
- npm start
83
- ```
20
+ Four tools covering the ntfy publish/subscribe surface — message lifecycle (publish, manage, fetch) plus an emoji-tag lookup that feeds the publish tool's `tags` field:
84
21
 
85
- 3. **Add to MCP Client Settings:** Add the server to your MCP client settings file (see [Configuration](#configuration))
22
+ | Tool Name | Description |
23
+ |:----------|:------------|
24
+ | `ntfy_publish_message` | Send or update a push notification on an ntfy topic. |
25
+ | `ntfy_manage_message` | Clear or delete a previously-sent notification by `sequence_id`. |
26
+ | `ntfy_fetch_messages` | Poll cached messages from one or more topics with optional filters. |
27
+ | `ntfy_search_emoji_tags` | Look up ntfy emoji tag short codes for use in `tags`. |
86
28
 
87
- 4. **Use the tool:** Once connected, you can use the `send_ntfy` tool to send notifications.
29
+ ---
88
30
 
89
- ## Installation
31
+ ### `ntfy_publish_message`
90
32
 
91
- ### Option 1: NPM Package (Recommended)
33
+ Send or update a push notification on an ntfy topic. Topics are created on first publish — treat the topic name as a secret because anyone who knows it can publish or subscribe.
92
34
 
93
- 1. **Install the package globally:**
35
+ - Full publish-parameter coverage — `title`, `priority` (1–5), `tags`, `click`, `attach`, `icon`, `filename`, `markdown`, `delay`, `email`, `call`, `cache`, `firebase`
36
+ - Up to three discriminated action buttons (`view`, `broadcast`, `http`, `copy`) per message
37
+ - Update or replace previously-sent messages by passing the original `sequence_id`
38
+ - Per-call `base_url` override that forwards credentials only when the override matches a registered server (`NTFY_BASE_URL` or an `NTFY_SERVERS` entry); otherwise the request goes out unauthenticated, so credentials never leak to alternate hosts
94
39
 
95
- ```bash
96
- npm install -g ntfy-mcp-server
97
- ```
40
+ ---
98
41
 
99
- This will install the server globally, making it available as a command-line tool.
42
+ ### `ntfy_manage_message`
100
43
 
101
- 2. **Or install locally in your project:**
44
+ Clear (mark read & dismiss) or delete a previously-sent ntfy notification by `sequence_id`. Append-only — the original message stays in cache, and a `message_clear` / `message_delete` event is emitted to subscribers. Idempotent.
102
45
 
103
- ```bash
104
- npm install ntfy-mcp-server
105
- ```
46
+ ---
106
47
 
107
- When installed locally, you can run it via npx or from node.
48
+ ### `ntfy_fetch_messages`
108
49
 
109
- ### Option 2: From Source
50
+ Poll cached messages from one or more topics with optional filters. Returns a snapshot, not a live stream — use it to confirm delivery, replay missed alerts, or audit topic activity.
110
51
 
111
- 1. **Clone the repository:**
52
+ - Comma-separated multi-topic queries (e.g. `alerts,backups,phil_alerts`)
53
+ - Filter by `since` (duration / timestamp / message ID / `all` / `latest`), `priority`, `tags`, `id`, `title`, `message`, scheduled-only
54
+ - Default window `10m`, default limit 20 messages per response, hard cap 100
55
+ - Long bodies truncated to ~500 chars with `messageTruncated` reporting the dropped count
112
56
 
113
- ```bash
114
- git clone https://github.com/cyanheads/ntfy-mcp-server.git
115
- cd ntfy-mcp-server
116
- ```
57
+ ---
117
58
 
118
- 2. **Install dependencies:**
59
+ ### `ntfy_search_emoji_tags`
119
60
 
120
- ```bash
121
- npm install
122
- ```
61
+ Substring search over the bundled ntfy emoji-tag reference. Returns the `tag` strings ready to plug into `ntfy_publish_message`'s `tags` field. Without a query, returns the first slice of the full reference.
123
62
 
124
- 3. **Build the project:**
125
- ```bash
126
- npm run build
127
- ```
63
+ ## Resources and prompts
128
64
 
129
- ## Configuration
65
+ | Type | Name | Description |
66
+ |:---|:---|:---|
67
+ | Resource | `ntfy://{topic}` | Snapshot of a topic — last 20 messages from the past 1 hour, plus the topic's browser URL. |
130
68
 
131
- ### Environment Variables
69
+ `ntfy_fetch_messages` covers the same topic data with custom windows and filters when the resource's fixed defaults aren't enough.
132
70
 
133
- Create a `.env` file in the project root based on `.env.example`:
71
+ ## Features
134
72
 
135
- ```bash
136
- # Ntfy Configuration
137
- NTFY_BASE_URL=https://ntfy.sh # Optional: Base URL of your ntfy instance
138
- NTFY_DEFAULT_TOPIC=your_default_topic # Optional: Default topic if none specified in requests
73
+ Built on [`@cyanheads/mcp-ts-core`](https://www.npmjs.com/package/@cyanheads/mcp-ts-core):
139
74
 
140
- # Application Configuration
141
- LOG_LEVEL=info # Optional: Logging level (debug, info, warn, error)
142
- NODE_ENV=development # Optional: Environment (development, production)
143
- ```
75
+ - Declarative tool and resource definitions — single file per primitive, framework handles registration and validation
76
+ - Typed error contracts via `ctx.fail(reason, …)` plus framework error factories (`forbidden`, `notFound`, `validationError`, …)
77
+ - Pluggable auth: `none`, `jwt`, `oauth`
78
+ - Swappable storage backends: `in-memory`, `filesystem`, `Supabase`, `Cloudflare KV/R2/D1`
79
+ - Structured logging with optional OpenTelemetry tracing
80
+ - STDIO and Streamable HTTP transports
144
81
 
145
- ### MCP Client Settings
82
+ ntfy-specific:
146
83
 
147
- #### For Cline VSCode Extension
84
+ - Wraps ntfy's HTTP API with retry-aware client (`withRetry` + per-request timeout)
85
+ - Per-server scoped auth — credentials are bound to each registered base URL (`NTFY_BASE_URL` or per-entry under `NTFY_SERVERS`); per-call `base_url` overrides forward auth only when the override matches a registered server, and go out unauthenticated otherwise
86
+ - Bundled emoji-tag reference, regenerated from upstream `docs/ntfy/emojis.md` via `scripts/build-emoji-tags.ts`
87
+ - Mutually-exclusive auth modes (bearer token *or* basic auth) validated at config-load time
148
88
 
149
- Add the following configuration to your Cline MCP settings file (usually located at `~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` on macOS):
89
+ ## Getting started
150
90
 
151
- ##### If installed globally:
91
+ Add the following to your MCP client configuration file. Public ntfy.sh works out of the box without an account; for protected topics, generate an access token at <https://ntfy.sh/account>.
152
92
 
153
93
  ```json
154
94
  {
155
95
  "mcpServers": {
156
96
  "ntfy": {
157
- "command": "ntfy-mcp-server",
97
+ "type": "stdio",
98
+ "command": "bunx",
99
+ "args": ["ntfy-mcp-server@latest"],
158
100
  "env": {
159
- "NTFY_BASE_URL": "https://ntfy.sh",
160
- "NTFY_DEFAULT_TOPIC": "your_default_topic",
161
- "LOG_LEVEL": "info",
162
- "NODE_ENV": "production"
101
+ "MCP_TRANSPORT_TYPE": "stdio",
102
+ "MCP_LOG_LEVEL": "info",
103
+ "NTFY_DEFAULT_TOPIC": "your-topic-name"
163
104
  }
164
105
  }
165
106
  }
166
107
  }
167
108
  ```
168
109
 
169
- ##### If installed from source:
110
+ Or with Docker:
170
111
 
171
112
  ```json
172
113
  {
173
114
  "mcpServers": {
174
115
  "ntfy": {
175
- "command": "node",
176
- "args": ["/path/to/ntfy-mcp-server/dist/index.js"],
177
- "env": {
178
- "NTFY_BASE_URL": "https://ntfy.sh",
179
- "NTFY_DEFAULT_TOPIC": "your_default_topic",
180
- "LOG_LEVEL": "info",
181
- "NODE_ENV": "production"
182
- }
116
+ "type": "stdio",
117
+ "command": "docker",
118
+ "args": [
119
+ "run", "-i", "--rm",
120
+ "-e", "MCP_TRANSPORT_TYPE=stdio",
121
+ "-e", "NTFY_DEFAULT_TOPIC=your-topic-name",
122
+ "ghcr.io/cyanheads/ntfy-mcp-server:latest"
123
+ ]
183
124
  }
184
125
  }
185
126
  }
186
127
  ```
187
128
 
188
- #### For Claude Desktop App
129
+ For Streamable HTTP, set the transport and start the server:
189
130
 
190
- Add the following configuration to your Claude Desktop config file (usually located at `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
191
-
192
- ##### If installed globally:
193
-
194
- ```json
195
- {
196
- "mcpServers": {
197
- "ntfy": {
198
- "command": "ntfy-mcp-server",
199
- "env": {
200
- "NTFY_BASE_URL": "https://ntfy.sh",
201
- "NTFY_DEFAULT_TOPIC": "your_default_topic",
202
- "LOG_LEVEL": "info",
203
- "NODE_ENV": "production"
204
- }
205
- }
206
- }
207
- }
131
+ ```sh
132
+ MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 NTFY_DEFAULT_TOPIC=your-topic bun run start:http
133
+ # Server listens at http://127.0.0.1:3010/mcp
208
134
  ```
209
135
 
210
- ##### If installed from source:
136
+ ### Prerequisites
211
137
 
212
- ```json
213
- {
214
- "mcpServers": {
215
- "ntfy": {
216
- "command": "node",
217
- "args": ["/path/to/ntfy-mcp-server/dist/index.js"],
218
- "env": {
219
- "NTFY_BASE_URL": "https://ntfy.sh",
220
- "NTFY_DEFAULT_TOPIC": "your_default_topic",
221
- "LOG_LEVEL": "info",
222
- "NODE_ENV": "production"
223
- }
224
- }
225
- }
226
- }
227
- ```
228
-
229
- _For source installation, replace `/path/to/ntfy-mcp-server/dist/index.js` with the actual absolute path to the built server file._
230
- _Adjust `env` variables as needed for your setup._
231
-
232
- ### Ntfy Setup
138
+ - [Bun v1.3.11](https://bun.sh/) or higher (or Node.js v24+).
139
+ - A topic name on an ntfy server. Public `ntfy.sh` requires no account; self-hosted instances and protected topics may need a bearer token or basic-auth credentials.
233
140
 
234
- 1. **Install the ntfy app** on your devices from [ntfy.sh](https://ntfy.sh/app) or the app stores
235
- 2. **Subscribe to your topic** in the app
236
- 3. **Use the same topic** in your MCP server configuration
141
+ ### Installation
237
142
 
238
- ## Project Structure
143
+ 1. **Clone the repository:**
239
144
 
145
+ ```sh
146
+ git clone https://github.com/cyanheads/ntfy-mcp-server.git
240
147
  ```
241
- .
242
- ├── .env.example # Example environment variables
243
- ├── .gitignore # Git ignore patterns
244
- ├── LICENSE # Project license (Apache-2.0)
245
- ├── package.json # Project metadata and dependencies
246
- ├── tsconfig.json # TypeScript compiler configuration
247
- ├── docs/
248
- │ └── tree.md # Auto-generated directory structure
249
- ├── logs/ # Runtime logs (created automatically)
250
- ├── scripts/ # Utility scripts
251
- │ ├── clean.ts # Cleans build artifacts and logs
252
- │ └── tree.ts # Generates the docs/tree.md file
253
- └── src/ # Source code
254
- ├── index.ts # Main server entry point
255
- ├── config/ # Configuration loading
256
- ├── mcp-server/ # MCP server logic, tools, and resources
257
- │ ├── resources/ # MCP resource implementations
258
- │ ├── tools/ # MCP tool implementations
259
- │ └── utils/ # MCP-specific utilities
260
- ├── services/ # External service integrations (ntfy)
261
- ├── types-global/ # Global type definitions
262
- └── utils/ # General utility functions
263
- ```
264
-
265
- ## Tools
266
148
 
267
- ### `send_ntfy`
268
-
269
- Sends a notification message via the ntfy service.
270
-
271
- #### Key Arguments:
272
-
273
- | Parameter | Type | Required | Description |
274
- | ------------ | -------- | -------- | ---------------------------------------------------------------------------- |
275
- | `topic` | string | Yes | The ntfy topic to publish to. |
276
- | `message` | string | Yes | The main content of the notification (max 4096 bytes). |
277
- | `title` | string | No | Notification title (max 250 bytes). |
278
- | `tags` | string[] | No | Emojis or keywords for categorization (e.g., `["warning", "robot"]`). Max 5. |
279
- | `priority` | integer | No | Message priority: 1=min, 2=low, 3=default, 4=high, 5=max. |
280
- | `click` | string | No | URL to open when the notification is clicked. |
281
- | `actions` | array | No | Action buttons (view, http, broadcast). Max 3. |
282
- | `attachment` | object | No | URL and name of an attachment. |
283
- | `email` | string | No | Email address to forward the notification to. |
284
- | `delay` | string | No | Delay delivery (e.g., `30m`, `1h`, `tomorrow`). |
285
- | `cache` | string | No | Cache duration (e.g., `10m`, `1h`, `1d`). |
286
- | `firebase` | string | No | Firebase Cloud Messaging (FCM) topic to forward to. |
287
- | `id` | string | No | Unique ID for the message. |
288
- | `expires` | string | No | Message expiration (e.g., `10m`, `1h`, `1d`). |
289
- | `markdown` | boolean | No | Set to `true` to enable markdown formatting in the message. |
290
- | `baseUrl` | string | No | Override the default ntfy server URL for this request. |
291
-
292
- #### Example Usage:
293
-
294
- ```javascript
295
- // Basic notification
296
- {
297
- "topic": "alerts",
298
- "message": "The task has completed successfully."
299
- }
149
+ 2. **Navigate into the directory:**
300
150
 
301
- // Advanced notification
302
- {
303
- "topic": "alerts",
304
- "title": "System Alert",
305
- "message": "CPU usage has exceeded 90% for 5 minutes.",
306
- "tags": ["warning", "computer"],
307
- "priority": 4,
308
- "click": "https://server-dashboard.example.com",
309
- "actions": [
310
- {
311
- "id": "view",
312
- "label": "View Details",
313
- "action": "view",
314
- "url": "https://server-dashboard.example.com/cpu"
315
- },
316
- {
317
- "id": "restart",
318
- "label": "Restart Service",
319
- "action": "http",
320
- "url": "https://api.example.com/restart-service",
321
- "method": "POST",
322
- "headers": {
323
- "Authorization": "Bearer token123"
324
- }
325
- }
326
- ],
327
- "markdown": true
328
- }
151
+ ```sh
152
+ cd ntfy-mcp-server
329
153
  ```
330
154
 
331
- #### Example Response:
155
+ 3. **Install dependencies:**
332
156
 
333
- ```json
334
- {
335
- "success": true,
336
- "id": "5ZFY362156Sa",
337
- "topic": "ATLAS",
338
- "time": 1743064235,
339
- "expires": 1743496235,
340
- "message": "This is a test message from the README verification process",
341
- "title": "README Testing"
342
- }
157
+ ```sh
158
+ bun install
343
159
  ```
344
160
 
345
- ## Resources
161
+ 4. **Configure environment:**
346
162
 
347
- ### Direct Resources
163
+ ```sh
164
+ cp .env.example .env
165
+ # edit .env and set NTFY_DEFAULT_TOPIC (and auth, if needed)
166
+ ```
348
167
 
349
- #### `ntfy://default`
168
+ ## Configuration
350
169
 
351
- - **Description:** Returns the default ntfy topic configured in the server's environment variables (`NTFY_DEFAULT_TOPIC`).
352
- - **Usage:** Useful for clients to discover the primary topic without needing prior configuration.
353
- - **Example:** An LLM agent can access this resource to automatically use the default topic when sending notifications.
354
- - **Example Response:**
355
- ```json
356
- {
357
- "defaultTopic": "ATLAS",
358
- "timestamp": "2025-03-27T08:30:25.619Z",
359
- "requestUri": "ntfy://default",
360
- "requestId": "0da963d0-30e0-4dbc-bb77-4bf2dee14484"
361
- }
170
+ | Variable | Description | Default |
171
+ |:---------|:------------|:--------|
172
+ | `NTFY_SERVERS` | JSON array of `{ baseUrl, authToken? \| authUsername?+authPassword? }` entries — one per ntfy server. First entry is the default base. Auth is scoped to the entry's `baseUrl`; per-call `base_url` overrides that match a registered base forward that server's auth. Use this when you need more than one authenticated server in a single process; it takes precedence over the single-server vars below. | — |
173
+ | `NTFY_BASE_URL` | Single-server shorthand — base URL of the ntfy server (no trailing slash). Used when `NTFY_SERVERS` is unset. | `https://ntfy.sh` |
174
+ | `NTFY_DEFAULT_TOPIC` | Topic used when a tool call omits `topic`. | — |
175
+ | `NTFY_AUTH_TOKEN` | Bearer access token (`tk_…`) for the single-server shorthand. Mutually exclusive with `NTFY_AUTH_USERNAME` / `NTFY_AUTH_PASSWORD`. | — |
176
+ | `NTFY_AUTH_USERNAME` | Basic-auth username for the single-server shorthand — required together with `NTFY_AUTH_PASSWORD`. | — |
177
+ | `NTFY_AUTH_PASSWORD` | Basic-auth password for the single-server shorthand — required together with `NTFY_AUTH_USERNAME`. | — |
178
+ | `NTFY_REQUEST_TIMEOUT_MS` | Per-request HTTP timeout in milliseconds. | `15000` |
179
+ | `NTFY_MAX_RETRIES` | Max retry attempts for transient upstream failures (5xx, network, 429). | `3` |
180
+ | `MCP_TRANSPORT_TYPE` | Transport: `stdio` or `http`. | `stdio` |
181
+ | `MCP_SESSION_MODE` | HTTP session model: `stateless`, `stateful`, or `auto`. | `auto` |
182
+ | `MCP_HTTP_HOST` | HTTP host. | `127.0.0.1` |
183
+ | `MCP_HTTP_PORT` | HTTP port. | `3010` |
184
+ | `MCP_HTTP_ENDPOINT_PATH` | HTTP endpoint path. | `/mcp` |
185
+ | `MCP_AUTH_MODE` | Auth mode: `none`, `jwt`, or `oauth`. | `none` |
186
+ | `MCP_LOG_LEVEL` | Log level (RFC 5424). | `info` |
187
+ | `LOGS_DIR` | Directory for file-based logs (Node only; ignored on Workers). | `./logs` |
188
+ | `OTEL_ENABLED` | Enable [OpenTelemetry instrumentation](https://github.com/cyanheads/mcp-ts-core/tree/main/docs/telemetry) (spans, metrics, completion logs). | `false` |
189
+
190
+ See [`.env.example`](./.env.example) for the full list of optional overrides.
191
+
192
+ ## Running the server
193
+
194
+ ### Local development
195
+
196
+ - **Build and run:**
197
+
198
+ ```sh
199
+ # One-time build
200
+ bun run rebuild
201
+
202
+ # Run the built server
203
+ bun run start:stdio
204
+ # or
205
+ bun run start:http
362
206
  ```
363
207
 
364
- ### Resource Templates
365
-
366
- #### `ntfy://{topic}`
208
+ - **Run checks and tests:**
367
209
 
368
- - **Description:** Returns information about a specific ntfy topic.
369
- - **Parameters:** `topic` - The name of the ntfy topic.
370
- - **Usage:** For querying information about topics other than the default.
371
- - **Example Response:**
372
- ```json
373
- {
374
- "topic": "ATLAS",
375
- "timestamp": "2025-03-27T08:30:30.038Z",
376
- "requestUri": "ntfy://ATLAS",
377
- "requestId": "31baf1df-278f-4fdb-860d-019f156a72b0"
378
- }
210
+ ```sh
211
+ bun run devcheck # Lint, format, typecheck, security, changelog sync
212
+ bun run test # Vitest test suite
213
+ bun run lint:mcp # Validate MCP definitions against spec
379
214
  ```
380
215
 
381
- ## Use Cases
382
-
383
- 1. **Long-running Task Notifications** - Get notified when tasks like database backups, code generation, or data processing complete.
384
- 2. **Scheduled Reminders** - Set delayed notifications for future events or reminders.
385
- 3. **Alert Systems** - Set up critical alerts for monitoring systems or important events.
386
- 4. **Mobile Notifications from LLMs** - Allow LLMs to send notifications directly to your phone.
387
- 5. **Multi-step Process Updates** - Receive updates as different stages of a complex process complete.
388
-
389
- ### Usage Examples
216
+ ### Docker
390
217
 
391
- #### Basic Notification
392
-
393
- ```
394
- <use_mcp_tool>
395
- <server_name>ntfy-mcp-server</server_name>
396
- <tool_name>send_ntfy</tool_name>
397
- <arguments>
398
- {
399
- "topic": "updates",
400
- "title": "Task Completed",
401
- "message": "Your requested data analysis has finished",
402
- "tags": ["check"]
403
- }
404
- </arguments>
405
- </use_mcp_tool>
218
+ ```sh
219
+ docker build -t ntfy-mcp-server .
220
+ docker run --rm -e NTFY_DEFAULT_TOPIC=your-topic -p 3010:3010 ntfy-mcp-server
406
221
  ```
407
222
 
408
- #### Rich Notification with Actions
223
+ The Dockerfile defaults to HTTP transport, stateless session mode, and logs to `/var/log/ntfy-mcp-server`. OpenTelemetry peer dependencies are installed by default — build with `--build-arg OTEL_ENABLED=false` to omit them.
409
224
 
410
- ```
411
- <use_mcp_tool>
412
- <server_name>ntfy-mcp-server</server_name>
413
- <tool_name>send_ntfy</tool_name>
414
- <arguments>
415
- {
416
- "topic": "alerts",
417
- "title": "Critical Error Detected",
418
- "message": "The application has encountered a critical error.\n\n**Error Code**: E123\n\n**Details**: Database connection failed",
419
- "tags": ["warning", "skull"],
420
- "priority": 5,
421
- "actions": [
422
- {
423
- "id": "view",
424
- "label": "View Logs",
425
- "action": "view",
426
- "url": "https://logs.example.com"
427
- },
428
- {
429
- "id": "restart",
430
- "label": "Restart Service",
431
- "action": "http",
432
- "url": "https://api.example.com/restart",
433
- "method": "POST"
434
- }
435
- ],
436
- "markdown": true
437
- }
438
- </arguments>
439
- </use_mcp_tool>
440
- ```
225
+ ## Project structure
441
226
 
442
- ## Available Scripts
227
+ | Directory | Purpose |
228
+ |:----------|:--------|
229
+ | `src/index.ts` | `createApp()` entry point — registers tools and resources, initializes services. |
230
+ | `src/config` | Server-specific environment variable parsing (`NTFY_*`) with Zod. |
231
+ | `src/mcp-server/tools` | Tool definitions (`*.tool.ts`). |
232
+ | `src/mcp-server/resources` | Resource definitions (`*.resource.ts`). |
233
+ | `src/services/ntfy` | ntfy HTTP client, types, and error classifier. |
234
+ | `src/services/emoji-tags` | Bundled emoji short-code reference and lookup service. |
235
+ | `docs/ntfy` | Mirrored upstream ntfy API docs (pinned commit in `SOURCES.md`). |
236
+ | `tests/` | Unit and integration tests mirroring `src/`. |
443
237
 
444
- - `npm run build`: Compiles the TypeScript source code to JavaScript in the `dist/` directory.
445
- - `npm run clean`: Removes the `dist/` directory and cleans the contents of the `logs/` directory.
446
- - `npm run rebuild`: Runs `clean` and then `build`.
447
- - `npm run tree`: Generates a directory tree representation in `docs/tree.md`.
448
- - `npm start`: Runs the compiled server from the `dist/` directory using Node.js.
449
- - `npm run watch`: Tails the combined log file (`logs/combined.log`) for real-time monitoring.
238
+ ## Development guide
450
239
 
451
- ## Contributing
452
-
453
- Contributions are welcome! Please feel free to submit pull requests or open issues to improve the project.
240
+ See [`CLAUDE.md`](./CLAUDE.md) for development guidelines and architectural rules. The short version:
454
241
 
455
- 1. Fork the repository.
456
- 2. Create a feature branch (`git checkout -b feature/your-feature`).
457
- 3. Commit your changes (`git commit -m 'Add some feature'`).
458
- 4. Push to the branch (`git push origin feature/your-feature`).
459
- 5. Create a new Pull Request.
242
+ - Handlers throw, framework catches — no `try/catch` in tool logic
243
+ - Use `ctx.log` for request-scoped logging, `ctx.state` for tenant-scoped storage
244
+ - Wrap external API calls: validate raw normalize to domain type → return output schema; never fabricate missing fields
245
+ - Per-tool `errors[]` contracts stay inline repetition is intended for locality
460
246
 
461
- For bugs and feature requests, please create an issue on the repository.
247
+ ## Contributing
462
248
 
463
- ### Development Best Practices
249
+ Issues and pull requests are welcome. Run checks and tests before submitting:
464
250
 
465
- - Follow TypeScript best practices and maintain strong typing
466
- - Write tests for new functionality
467
- - Keep dependencies up to date
468
- - Follow the existing code style and patterns
251
+ ```sh
252
+ bun run devcheck
253
+ bun run test
254
+ ```
469
255
 
470
256
  ## License
471
257
 
472
- This project is licensed under the Apache-2.0 License. See the [LICENSE](LICENSE) file for details.
473
-
474
- ## Acknowledgements
475
-
476
- - [ntfy.sh](https://ntfy.sh/) for providing the notification service
477
- - [Model Context Protocol](https://modelcontextprotocol.io/) for enabling LLM-to-tool connections
478
- - All contributors and users of this project
479
-
480
- ---
481
-
482
- <div align="center">
483
- Built with the Model Context Protocol
484
- </div>
258
+ Apache-2.0 see [LICENSE](LICENSE) for details.