Skip to content

Commit de81930

Browse files
committed
Add new tool for ntfy_me_fetch
Add filters for fetching messages from ntfy and improve tool discoverability using natural language update readme and npm version
1 parent d754be9 commit de81930

File tree

7 files changed

+580
-48
lines changed

7 files changed

+580
-48
lines changed

README.md

Lines changed: 119 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,20 @@
1111

1212
> A streamlined Model Context Protocol (MCP) server for sending notifications via ntfy service (public or selfhosted with token support) 📲
1313
14-
### Available via:
15-
16-
| Name | Link / Badge |
17-
|------|------|
18-
| Glama.ai | <a href="https://glama.ai/mcp/servers/@gitmotion/ntfy-me-mcp"><img width="250" src="https://glama.ai/mcp/servers/@gitmotion/ntfy-me-mcp/badge" alt="ntfy-me-mcp MCP server" /></a> |
19-
| Smithery.ai | [![smithery badge](https://smithery.ai/badge/@gitmotion/ntfy-me-mcp)](https://smithery.ai/server/@gitmotion/ntfy-me-mcp) |
2014
## Overview
2115

2216
ntfy-me-mcp provides AI assistants with the ability to send real-time notifications to your devices through the [ntfy](https://ntfy.sh) service (either public or selfhosted with token support). Get notified when your AI completes tasks, encounters errors, or reaches important milestones - all without constant monitoring.
2317

2418
The server includes intelligent features like automatic URL detection for creating view actions and smart markdown formatting detection, making it easier for AI assistants to create rich, interactive notifications without extra configuration.
2519

26-
<details>
27-
<summary>Intelligent Auto Detect Preview:</summary>
28-
2920
<img src="https://github.com/user-attachments/assets/5a79f377-8a5e-4c56-a6f6-1aff5d70ee0c" alt="autodetect-preview" width=50%>
30-
</details>
21+
22+
### Available via:
23+
24+
| Name | Link / Badge |
25+
|------|------|
26+
| Glama.ai | <a href="https://glama.ai/mcp/servers/@gitmotion/ntfy-me-mcp"><img width="250" src="https://glama.ai/mcp/servers/@gitmotion/ntfy-me-mcp/badge" alt="ntfy-me-mcp MCP server" /></a> |
27+
| Smithery.ai | [![smithery badge](https://smithery.ai/badge/@gitmotion/ntfy-me-mcp)](https://smithery.ai/server/@gitmotion/ntfy-me-mcp) |
3128

3229
## Table of Contents
3330

@@ -51,16 +48,20 @@ The server includes intelligent features like automatic URL detection for creati
5148
- [Configuration](#configuration)
5249
- [Environment Variables](#environment-variables)
5350
- [Usage](#usage)
54-
- [Authentication](#authentication)
55-
- [Setting Up the Notification Receiver](#setting-up-the-notification-receiver)
56-
- [Using with AI Assistants](#using-with-ai-assistants)
57-
- [Notification Parameters](#notification-parameters)
58-
- [Action Links](#action-links)
59-
- [Emoji Shortcodes](#emoji-shortcodes)
60-
- [Markdown Formatting](#markdown-formatting)
61-
- [Example Notification](#example-notification)
62-
- [Development](#development)
63-
- [Building from Source](#building-from-source)
51+
- [Authentication](#authentication)
52+
- [Setting Up the Notification Receiver](#setting-up-the-notification-receiver)
53+
- [Sending Notifications (ntfy_me tool)](#sending-notifications-ntfy_me-tool)
54+
- [Using Natural Language](#using-natural-language)
55+
- [Message Parameters](#message-parameters)
56+
- [Action Links](#action-links)
57+
- [Emoji Shortcodes](#emoji-shortcodes)
58+
- [Markdown Formatting](#markdown-formatting)
59+
- [Retrieving Messages (ntfy_me_fetch tool)](#retrieving-messages-ntfy_me_fetch-tool)
60+
- [Using Natural Language](#using-natural-language-1)
61+
- [Message Parameters](#message-parameters-1)
62+
- [Examples](#examples)
63+
- [Development](#development)
64+
- [Building from Source](#building-from-source)
6465
- [License](#license)
6566
- [Contributing](#contributing)
6667

@@ -69,14 +70,15 @@ The server includes intelligent features like automatic URL detection for creati
6970
- 🚀 **Quick Setup**: Run with npx or docker!
7071
- 🔔 **Real-time Notifications**: Get updates on your phone/desktop when tasks complete
7172
- 🎨 **Rich Notifications**: Support for topic, title, priorities, emoji tags, and detailed messages
73+
- 🔍 **Notification Fetching**: Fetch and filter cached messages from your ntfy topics
7274
- 🎯 **Smart Action Links**: Automatically detects URLs in messages and creates view actions
7375
- 📄 **Intelligent Markdown**: Auto-detects and enables markdown formatting when present
7476
- 🔒 **Secure**: Optional authentication with access tokens
7577
- 🔑 **Input Masking**: Securely store your ntfy token in your vs config!
7678
- 🌐 **Self-hosted Support**: Works with both ntfy.sh and self-hosted ntfy instances
7779

7880
### (Coming soon...)
79-
- 📨 **Email**: Send notifications to email (requires ntfy email server configuration)
81+
- 📨 **Email**: Send notifications to email (requires ntfy email server configuration)
8082
- 🔗 **Click urls**: Ability to customize click urls
8183
- 🖼️ **Image urls**: Intelligent image url detection to automatically include image urls in messages and notifications
8284
- 🏁 and more!
@@ -332,17 +334,22 @@ If authentication is required but not provided, you'll receive a clear error mes
332334
1. Install the [ntfy app](https://ntfy.sh/app) on your device
333335
2. Subscribe to your chosen topic (the same as your `NTFY_TOPIC` setting)
334336

335-
### Using with AI Assistants
337+
### Sending Notifications (ntfy_me tool)
338+
339+
This section covers all functionality related to sending notifications using the ntfy_me tool.
336340

337-
When working with your AI assistant, include phrases like:
341+
#### Using Natural Language
338342

343+
When working with your AI assistant, you can use natural phrases like:
339344
```
340-
Write me a React component, and notify me when it's done.
345+
"Send me a notification when the build is complete"
346+
"Notify me when the task is done"
347+
"Alert me after generating the code"
348+
"Message me when the process finishes"
349+
"Send an alert with high priority"
341350
```
342351

343-
Your AI will use the `ntfy_me` tool to send a notification upon task completion.
344-
345-
### Notification Parameters
352+
#### Message Parameters
346353

347354
The tool accepts these parameters:
348355

@@ -355,11 +362,23 @@ The tool accepts these parameters:
355362
| markdown | Boolean to enable markdown formatting (true/false) | No |
356363
| actions | Array of view action objects for clickable links | No |
357364

358-
### Action Links
365+
Example:
366+
```javascript
367+
{
368+
taskTitle: "Code Generation Complete",
369+
taskSummary: "Your React component has been created successfully with proper TypeScript typing.",
370+
priority: "high",
371+
tags: ["check", "code", "react"]
372+
}
373+
```
374+
375+
This will send a high-priority notification with a checkmark emoji.
376+
377+
#### Action Links
359378

360379
You can add clickable action buttons to your notifications using the `actions` parameter, or let the server automatically detect URLs in your message.
361380

362-
#### Automatic URL Detection
381+
##### Automatic URL Detection
363382
When URLs are present in your message body, the server automatically creates up to 3 view actions (ntfy's maximum limit) from the first detected URLs. This makes it easy to include clickable links without manually specifying the actions array.
364383

365384
For example, this message:
@@ -372,7 +391,7 @@ For example, this message:
372391

373392
Will automatically generate view actions for both URLs, making them easily clickable in the notification.
374393

375-
#### Manual Action Configuration
394+
##### Manual Action Configuration
376395
For more control, you can manually specify actions:
377396

378397
| Property | Description | Required |
@@ -406,7 +425,7 @@ Example with action links:
406425
}
407426
```
408427

409-
### Emoji Shortcodes
428+
#### Emoji Shortcodes
410429

411430
You can use emoji shortcodes in your tags for visual indicators:
412431

@@ -417,11 +436,11 @@ You can use emoji shortcodes in your tags for visual indicators:
417436

418437
See the [full list of supported emoji shortcodes](https://docs.ntfy.sh/emojis/).
419438

420-
### Markdown Formatting
439+
#### Markdown Formatting
421440

422441
Your notifications support rich markdown formatting with intelligent detection! When you include markdown syntax in your `taskSummary`, the server automatically detects it and enables markdown parsing - no need to set `markdown: true` explicitly.
423442

424-
#### Automatic Detection
443+
##### Automatic Detection
425444
The server checks for common markdown patterns like:
426445
- Headers (#, ##, etc.)
427446
- Lists (-, *, numbers)
@@ -431,7 +450,7 @@ The server checks for common markdown patterns like:
431450

432451
When these patterns are detected, markdown parsing is automatically enabled for the message.
433452

434-
#### Manual Override
453+
##### Manual Override
435454
While automatic detection works in most cases, you can still explicitly control markdown parsing:
436455
```javascript
437456
{
@@ -441,18 +460,78 @@ While automatic detection works in most cases, you can still explicitly control
441460
}
442461
```
443462

444-
### Example Notification
463+
### Retrieving Messages (ntfy_me_fetch tool)
464+
465+
This section covers all functionality related to fetching and filtering messages using the ntfy_me_fetch tool.
466+
467+
#### Using Natural Language
468+
469+
AI assistants understand various ways to request message fetching:
470+
```
471+
"Show me my recent notifications"
472+
"Get messages from the last hour"
473+
"Find notifications with title 'Build Complete'"
474+
"Search for messages with the test_tube tag"
475+
"Show notifications from the updates topic from the last 24hr"
476+
"Check my latest alerts"
477+
```
478+
479+
#### Message Parameters
480+
481+
The tool accepts these parameters:
482+
483+
| Parameter | Description | Required |
484+
|-----------|-------------|----------|
485+
| ntfyTopic | Topic to fetch messages from (defaults to NTFY_TOPIC env var) | No |
486+
| since | How far back to retrieve messages ('10m', '1h', '1d', timestamp, message ID, or 'all') | No |
487+
| messageId | Find a specific message by its ID | No |
488+
| messageText | Find messages containing exact text content | No |
489+
| messageTitle | Find messages with exact title/subject | No |
490+
| priorities | Find messages with specific priority levels | No |
491+
| tags | Find messages with specific tags | No |
492+
493+
#### Examples
494+
495+
1. **Fetch Recent Messages**
496+
```javascript
497+
{
498+
since: "30m" // Get messages from last 30 minutes
499+
}
500+
```
501+
502+
2. **Filter by Title and Priority**
503+
```javascript
504+
{
505+
messageTitle: "Build Complete",
506+
priorities: "high",
507+
since: "1d"
508+
}
509+
```
445510

511+
3. **Search Different Topic with Tags**
446512
```javascript
447513
{
448-
taskTitle: "Code Generation Complete",
449-
taskSummary: "Your React component has been created successfully with proper TypeScript typing.",
450-
priority: "high",
451-
tags: ["check", "code", "react"]
514+
ntfyTopic: "updates",
515+
tags: ["error", "warning"],
516+
since: "all"
452517
}
453518
```
454519

455-
This will send a high-priority notification with a checkmark emoji.
520+
4. **Find Specific Message**
521+
```javascript
522+
{
523+
messageId: "xxxxXXXXxxxx"
524+
}
525+
```
526+
527+
Messages are returned with full details including:
528+
- Message ID and timestamp
529+
- Topic and title
530+
- Content and priority
531+
- Tags and attachments
532+
- Action links and expiration
533+
534+
> **Note**: Message history availability depends on your ntfy server's cache settings. The public ntfy.sh server typically caches messages for 12 hours.
456535
457536
## Development
458537

build/index.js

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { dirname, join } from "path";
1010
import fs from "fs";
1111
import { detectMarkdown } from "./utils/markdown.js";
1212
import { processActions } from "./utils/actions.js";
13+
import { fetchMessages } from "./utils/messages.js";
1314
// Get package.json path
1415
const __filename = fileURLToPath(import.meta.url);
1516
const __dirname = dirname(__filename);
@@ -62,7 +63,7 @@ async function initializeServer() {
6263
version: packageJson.version,
6364
});
6465
// Add the notify_user tool
65-
server.tool("ntfy_me", "Notify the user that certain task is complete/error/stopped and give the summary and title of the completed task", {
66+
server.tool("ntfy_me", "Send a notification to the user via ntfy. Use this tool when the user asks to 'send a notification', 'notify me', 'send me an alert', 'message me', 'ping me', or any similar request. This tool is perfect for sending status updates, alerts, reminders, or notifications about completed tasks.", {
6667
taskTitle: z.string().describe("Current task title/status"),
6768
taskSummary: z.string().describe("Current task summary"),
6869
ntfyUrl: z.string().optional().describe("Optional custom ntfy URL (defaults to NTFY_URL env var or https://ntfy.sh)"),
@@ -155,6 +156,76 @@ async function initializeServer() {
155156
};
156157
}
157158
});
159+
// Add the ntfy_me_fetch tool to fetch cached messages
160+
server.tool("ntfy_me_fetch", "Fetch cached messages from an ntfy server topic. Use this tool when the user asks to 'show notifications', 'get my messages', 'show my alerts', 'find notifications', 'search notifications', or any similar request. Great for finding recent notifications, checking message history, or searching for specific notifications by content, title, tags, or priority.", {
161+
ntfyUrl: z.string().optional().describe("Optional custom ntfy server URL (defaults to NTFY_URL env var or https://ntfy.sh)"),
162+
ntfyTopic: z.string().optional().describe("Optional custom ntfy topic/channel to get messages from (defaults to NTFY_TOPIC env var)"),
163+
accessToken: z.string().optional().describe("Optional access token for authentication (defaults to NTFY_TOKEN env var)"),
164+
since: z.union([z.string(), z.number()]).optional().describe("How far back to retrieve messages: timespan (e.g., '10m', '1h', '1d'), timestamp, message ID, or 'all' for all messages. Default: 10 minutes"),
165+
messageId: z.string().optional().describe("Find a specific message by its ID"),
166+
messageText: z.string().optional().describe("Find messages containing this exact text content"),
167+
messageTitle: z.string().optional().describe("Find messages with this exact title/subject"),
168+
priorities: z.union([z.string(), z.array(z.string())]).optional().describe("Find messages with specific priority levels (min, low, default, high, max)"),
169+
tags: z.union([z.string(), z.array(z.string())]).optional().describe("Find messages with specific tags (e.g., 'error', 'warning', 'success')"),
170+
}, async ({ ntfyUrl, ntfyTopic, accessToken, since, messageId, messageText, messageTitle, priorities, tags }) => {
171+
try {
172+
const url = ntfyUrl || NTFY_URL;
173+
const topic = ntfyTopic || NTFY_TOPIC;
174+
const token = accessToken || NTFY_TOKEN;
175+
// Default since to 10 minutes if not null
176+
const sinceSetting = since === null ? undefined : (since || "10m");
177+
// Fetch the messages with any provided filters
178+
const messageRecords = await fetchMessages({
179+
ntfyUrl: url,
180+
topic,
181+
token,
182+
since: sinceSetting,
183+
messageId,
184+
messageText,
185+
messageTitle,
186+
priorities,
187+
tags
188+
});
189+
if (!messageRecords) {
190+
return {
191+
content: [
192+
{
193+
type: "text",
194+
text: `No messages found in topic ${topic}`,
195+
},
196+
],
197+
};
198+
}
199+
// Format the response
200+
const messagesCount = Object.values(messageRecords).reduce((sum, messages) => sum + messages.length, 0);
201+
const formattedMessages = Object.entries(messageRecords).map(([topic, messages]) => {
202+
return {
203+
type: "text",
204+
text: `Topic: ${topic}\nMessages: ${messages.length}\n${JSON.stringify(messages, null, 2)}`
205+
};
206+
});
207+
return {
208+
content: [
209+
{
210+
type: "text",
211+
text: `Successfully fetched ${messagesCount} message(s) from ${Object.keys(messageRecords).length} topic(s)`,
212+
},
213+
...formattedMessages
214+
],
215+
};
216+
}
217+
catch (error) {
218+
return {
219+
content: [
220+
{
221+
type: "text",
222+
text: `Failed to fetch ntfy messages: ${error.message}`,
223+
},
224+
],
225+
isError: true,
226+
};
227+
}
228+
});
158229
// Start the server with stdio transport
159230
const transport = new StdioServerTransport();
160231
server

0 commit comments

Comments
 (0)