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.
100 lines (99 loc) • 3.66 kB
JavaScript
import { ErrorHandler } from "../utils/errorHandler.js";
import { logger } from "../utils/logger.js";
// Create a module-level logger
const toolLogger = logger.createChildLogger({
module: 'ToolRegistration'
});
/**
* Create a tool example
*
* @param input Example input parameters
* @param output Expected output (as a formatted string)
* @param description Description of what the example demonstrates
* @returns A tool example object
*/
export function createToolExample(input, output, description) {
return {
input,
output,
description
};
}
/**
* Create tool metadata
*
* @param metadata Tool metadata options
* @returns Tool metadata configuration
*/
export function createToolMetadata(metadata) {
return metadata;
}
/**
* Register a tool with the MCP server
*
* This is a compatibility wrapper for the McpServer.tool() method.
* In the current implementation, the tool registration is handled by the McpServer class,
* so this function primarily exists to provide a consistent API.
*
* @param server MCP server instance
* @param name Tool name
* @param description Tool description
* @param inputSchema Schema for validating input
* @param handler Handler function for the tool
* @param metadata Optional tool metadata
*/
export function registerTool(server, // Using any to avoid type conflicts
name, description, inputSchema, handler, metadata) {
return ErrorHandler.tryCatch(async () => {
// Log the registration attempt
toolLogger.info(`Registering tool: ${name}`, {
toolName: name,
schemaKeys: Object.keys(inputSchema),
hasMetadata: Boolean(metadata),
hasExamples: Boolean(metadata?.examples?.length)
});
// Some basic validation
if (!name) {
throw new Error('Tool name is required');
}
if (!inputSchema) {
throw new Error('Input schema is required');
}
if (!handler || typeof handler !== 'function') {
throw new Error('Handler must be a function');
}
// Convert schema to a more standardized format if needed
const schemaDescription = Object.entries(inputSchema).map(([key, schema]) => {
const description = schema.description;
const isRequired = !schema.isOptional?.();
return `${key}${isRequired ? ' (required)' : ''}: ${description || 'No description'}`;
}).join('\n');
toolLogger.debug(`Tool ${name} schema:`, {
toolName: name,
schema: schemaDescription
});
// Actually register the tool with the server
// Check if it's an McpServer instance with tool() method
if (server.tool && typeof server.tool === 'function') {
// Use the McpServer.tool() method directly
toolLogger.debug('Using McpServer.tool() method');
server.tool(name, inputSchema, handler, {
description,
examples: metadata?.examples
});
}
else {
// For other server types or for testing, log a warning
toolLogger.warn(`Unable to register tool ${name} with server - missing tool() method`, {
toolName: name
});
}
// Log successful registration
toolLogger.info(`Tool ${name} registered successfully`);
}, {
context: { toolName: name },
operation: "registering tool",
errorMapper: (error) => new Error(`Failed to register tool ${name}: ${error instanceof Error ? error.message : String(error)}`),
rethrow: true
});
}