#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import notifier from "node-notifier";
const server = new Server(
{
name: "mcp-notifications",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
// Define the show_notification tool
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "show_notification",
description: "Display a notification on macOS using the Notification Center. Can include a title, content message, and optional icon and sound.",
inputSchema: {
type: "object",
properties: {
title: {
type: "string",
description: "The title of the notification",
},
content: {
type: "string",
description: "The main content/message of the notification",
},
icon: {
type: "string",
description: "Optional path to an icon file to display with the notification",
},
sound: {
type: "string",
description: "Optional name of a system sound to play (e.g., 'Ping', 'Basso', 'Hero', 'Funk')",
},
},
required: ["title", "content"],
},
},
],
};
});
// Handle tool calls
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "show_notification") {
const { title, content, icon, sound } = request.params.arguments as {
title: string;
content: string;
icon?: string;
sound?: string;
};
try {
// Prepare notification options
const notificationOptions: any = {
title,
message: content,
};
// Add sound if provided
if (sound) {
notificationOptions.sound = sound;
}
// Add icon if provided
if (icon) {
notificationOptions.icon = icon;
}
// Send the notification
await new Promise<void>((resolve, reject) => {
notifier.notify(notificationOptions, (err, response) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
return {
content: [
{
type: "text",
text: `Notification sent successfully: "${title}"`,
},
],
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
return {
content: [
{
type: "text",
text: `Failed to send notification: ${errorMessage}`,
},
],
isError: true,
};
}
}
throw new Error(`Unknown tool: ${request.params.name}`);
});
// Start the server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Notifications Server running on stdio");
}
main().catch((error) => {
console.error("Server error:", error);
process.exit(1);
});