UNPKG

@the_cfdude/productboard-mcp

Version:

Model Context Protocol server for Productboard REST API with dynamic tool loading

100 lines (99 loc) 3.24 kB
/** * Custom error types for Productboard MCP server */ import { ErrorCode } from '@modelcontextprotocol/sdk/types.js'; export class ProductboardError extends Error { code; originalError; constructor(code, message, originalError) { super(message); this.code = code; this.originalError = originalError; this.name = 'ProductboardError'; } } export class ValidationError extends ProductboardError { field; constructor(message, field) { super(ErrorCode.InvalidRequest, message); this.field = field; this.name = 'ValidationError'; } } export class AuthenticationError extends ProductboardError { constructor(message = 'Authentication failed') { super(ErrorCode.InvalidRequest, message); this.name = 'AuthenticationError'; } } export class RateLimitError extends ProductboardError { retryAfter; constructor(retryAfter) { super(ErrorCode.InvalidRequest, `Rate limit exceeded${retryAfter ? `. Retry after ${retryAfter}s` : ''}`); this.retryAfter = retryAfter; this.name = 'RateLimitError'; } } export class NetworkError extends ProductboardError { constructor(message, originalError) { super(ErrorCode.InternalError, message, originalError); this.name = 'NetworkError'; } } export class ConfigurationError extends ProductboardError { constructor(message) { super(ErrorCode.InternalError, message); this.name = 'ConfigurationError'; } } /** * Sanitize error messages to prevent information leakage * Enhanced with contextual documentation hints */ export function sanitizeErrorMessage(error, toolName) { const docHint = toolName ? ` Use 'get_${getEntityTypeFromTool(toolName)}_docs()' for complete API documentation.` : ''; if (error instanceof ValidationError) { const message = error.field ? `Invalid ${error.field}` : 'Invalid input'; return `${message}.${docHint}`; } if (error instanceof AuthenticationError) { return `Authentication failed.${docHint}`; } if (error instanceof RateLimitError) { return `${error.message}.${docHint}`; } if (error instanceof NetworkError) { return `Network error occurred.${docHint}`; } if (error instanceof ConfigurationError) { return `Configuration error.${docHint}`; } // Generic error - don't expose details return `An error occurred processing your request.${docHint}`; } /** * Extract entity type from tool name for contextual documentation */ function getEntityTypeFromTool(toolName) { if (toolName.includes('feature')) return 'feature'; if (toolName.includes('note')) return 'note'; if (toolName.includes('component')) return 'component'; if (toolName.includes('product')) return 'product'; if (toolName.includes('company')) return 'company'; if (toolName.includes('user')) return 'user'; if (toolName.includes('objective')) return 'objective'; if (toolName.includes('initiative')) return 'initiative'; if (toolName.includes('release')) return 'release'; return 'general'; }