ntfy-mcp-server
Version:
An MCP (Model Context Protocol) server designed to interact with the ntfy push notification service. It enables LLMs and AI agents to send notifications to your devices with extensive customization options.
135 lines (134 loc) • 4.39 kB
JavaScript
/**
* Custom error classes for the ntfy service
*/
import { BaseErrorCode, McpError } from '../../types-global/errors.js';
import { ErrorHandler } from '../../utils/errorHandler.js';
/**
* Get message from an error object
* @param error The error to extract message from
* @returns Error message as string
*/
function getErrorMessage(error) {
if (error instanceof Error) {
return error.message;
}
if (error === null) {
return 'Null error occurred';
}
if (error === undefined) {
return 'Undefined error occurred';
}
return typeof error === 'string'
? error
: String(error);
}
/**
* Base error class for ntfy service errors
*/
export class NtfyError extends McpError {
constructor(message, details) {
const errorCode = details?.errorCode || BaseErrorCode.SERVICE_UNAVAILABLE;
super(errorCode, message, details);
this.name = 'NtfyError';
}
}
/**
* Error thrown when connection to ntfy server fails
*/
export class NtfyConnectionError extends NtfyError {
constructor(message, url) {
super(message, { url });
this.url = url;
this.name = 'NtfyConnectionError';
}
}
/**
* Error thrown when authentication fails
*/
export class NtfyAuthenticationError extends NtfyError {
constructor(message) {
super(message, { errorCode: BaseErrorCode.UNAUTHORIZED });
this.name = 'NtfyAuthenticationError';
this.code = BaseErrorCode.UNAUTHORIZED; // Ensure code is set correctly
}
}
/**
* Error thrown when a message cannot be parsed
*/
export class NtfyParseError extends NtfyError {
constructor(message, rawData) {
super(message, {
rawData: rawData?.substring(0, 100), // Truncate large data for logging
errorCode: BaseErrorCode.VALIDATION_ERROR
});
this.rawData = rawData;
this.name = 'NtfyParseError';
this.code = BaseErrorCode.VALIDATION_ERROR; // Ensure code is set correctly
}
}
/**
* Error thrown when a subscription is closed unexpectedly
*/
export class NtfySubscriptionClosedError extends NtfyError {
constructor(message, reason) {
super(message, { reason });
this.reason = reason;
this.name = 'NtfySubscriptionClosedError';
}
}
/**
* Error thrown when an invalid topic name is provided
*/
export class NtfyInvalidTopicError extends NtfyError {
constructor(message, topic) {
super(message, { topic, errorCode: BaseErrorCode.VALIDATION_ERROR });
this.topic = topic;
this.name = 'NtfyInvalidTopicError';
this.code = BaseErrorCode.VALIDATION_ERROR; // Ensure code is set correctly
}
}
/**
* Error thrown when a timeout occurs
*/
export class NtfyTimeoutError extends NtfyError {
constructor(message, timeoutMs) {
super(message, { timeoutMs, errorCode: BaseErrorCode.TIMEOUT });
this.timeoutMs = timeoutMs;
this.name = 'NtfyTimeoutError';
this.code = BaseErrorCode.TIMEOUT; // Ensure code is set correctly
}
}
/**
* Error mapping for ntfy errors
*/
export const NTFY_ERROR_MAPPINGS = [
{
pattern: /authentication|unauthorized|auth.*failed/i,
errorCode: BaseErrorCode.UNAUTHORIZED,
factory: (error) => new NtfyAuthenticationError(getErrorMessage(error))
},
{
pattern: /parse|invalid.*json|invalid.*format/i,
errorCode: BaseErrorCode.VALIDATION_ERROR,
factory: (error, context) => new NtfyParseError(getErrorMessage(error), context?.rawData)
},
{
pattern: /invalid.*topic/i,
errorCode: BaseErrorCode.VALIDATION_ERROR,
factory: (error, context) => new NtfyInvalidTopicError(getErrorMessage(error), context?.topic)
},
{
pattern: /timed out|timeout|deadline exceeded/i,
errorCode: BaseErrorCode.TIMEOUT,
factory: (error, context) => new NtfyTimeoutError(getErrorMessage(error), context?.timeoutMs)
},
{
pattern: /connection|network|failed to connect|refused/i,
errorCode: BaseErrorCode.SERVICE_UNAVAILABLE,
factory: (error, context) => new NtfyConnectionError(getErrorMessage(error), context?.url)
}
];
/**
* Create an error mapper function for ntfy errors
*/
export const ntfyErrorMapper = ErrorHandler.createErrorMapper(NTFY_ERROR_MAPPINGS, BaseErrorCode.SERVICE_UNAVAILABLE);