maplestory-mcp-server
Version:
Official-style NEXON MapleStory MCP Server for Claude Desktop - Complete character info, union details, guild data, rankings, and game mechanics
235 lines • 7.44 kB
JavaScript
;
/**
* Base tool interface and abstract classes for MCP Maple tools
* Provides common structure and functionality for all MapleStory API tools
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EnhancedBaseTool = exports.ToolCategory = exports.GuildTool = exports.CharacterTool = exports.BaseTool = void 0;
const ajv_1 = __importDefault(require("ajv"));
/**
* Abstract base class for all MCP tools
* Provides common functionality and structure
*/
class BaseTool {
static ajv = new ajv_1.default({ allErrors: true });
/**
* Execute the tool with given arguments
*/
async execute(args, context) {
const startTime = Date.now();
try {
// Validate input arguments
if (!this.validate(args)) {
throw new Error('Invalid arguments provided');
}
context.logger.info(`Executing tool: ${this.name}`, {
toolName: this.name,
arguments: args,
});
// Execute the tool-specific logic
const result = await this.executeImpl(args, context);
const executionTime = Date.now() - startTime;
context.logger.info(`Tool execution completed: ${this.name}`, {
toolName: this.name,
executionTime,
success: true,
});
return result;
}
catch (error) {
const executionTime = Date.now() - startTime;
context.logger.error(`Tool execution failed: ${this.name}`, {
toolName: this.name,
executionTime,
error: error instanceof Error ? error.message : String(error),
});
throw error;
}
}
/**
* Validate input arguments against the schema
*/
validate(args) {
try {
const validate = BaseTool.ajv.compile(this.inputSchema);
const isValid = validate(args);
if (!isValid) {
return false;
}
return this.validateImpl(args);
}
catch (error) {
return false;
}
}
/**
* Tool-specific validation logic
*/
validateImpl(_args) {
return true; // Override in subclasses for custom validation
}
/**
* Helper method to format tool results consistently
*/
formatResult(data, metadata) {
return {
success: true,
data,
...(metadata && { metadata }),
};
}
/**
* Helper method to format error results consistently
*/
formatError(error, metadata) {
return {
success: false,
error: error instanceof Error ? error.message : error,
...(metadata && { metadata }),
};
}
/**
* Helper method to safely get required string parameter
*/
getRequiredString(args, key) {
const value = args[key];
if (typeof value !== 'string' || value.trim() === '') {
throw new Error(`Required parameter '${key}' must be a non-empty string`);
}
return value.trim();
}
/**
* Helper method to safely get optional string parameter
*/
getOptionalString(args, key, defaultValue) {
const value = args[key];
if (value === undefined || value === null) {
return defaultValue;
}
if (typeof value !== 'string') {
throw new Error(`Parameter '${key}' must be a string`);
}
return value.trim();
}
/**
* Helper method to safely get required number parameter
*/
getRequiredNumber(args, key) {
const value = args[key];
if (typeof value !== 'number' || isNaN(value)) {
throw new Error(`Required parameter '${key}' must be a valid number`);
}
return value;
}
/**
* Helper method to safely get optional number parameter
*/
getOptionalNumber(args, key, defaultValue = 0) {
const value = args[key];
if (value === undefined || value === null) {
return defaultValue;
}
if (typeof value !== 'number' || isNaN(value)) {
throw new Error(`Parameter '${key}' must be a valid number`);
}
return value;
}
/**
* Helper method to get optional boolean parameter with default value
*/
getOptionalBoolean(args, key, defaultValue = false) {
const value = args[key];
if (value === undefined || value === null) {
return defaultValue;
}
if (typeof value !== 'boolean') {
throw new Error(`Parameter '${key}' must be a boolean`);
}
return value;
}
/**
* Helper method to validate date format (YYYY-MM-DD)
*/
validateDateFormat(date) {
const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
if (!dateRegex.test(date)) {
return false;
}
const parsedDate = new Date(date);
return parsedDate instanceof Date && !isNaN(parsedDate.getTime());
}
/**
* Helper method to format date to API format
*/
formatApiDate(date) {
const targetDate = date || new Date();
const isoString = targetDate.toISOString();
const datePart = isoString.split('T')[0];
if (!datePart) {
throw new Error('Invalid date format');
}
return datePart;
}
/**
* Helper method to handle API errors consistently
*/
handleApiError(error, operation) {
if (error?.error) {
throw new Error(`${operation} failed: ${error.error.message} (${error.error.name})`);
}
const message = error instanceof Error ? error.message : String(error);
throw new Error(`${operation} failed: ${message}`);
}
}
exports.BaseTool = BaseTool;
/**
* Abstract base class for character-related tools
*/
class CharacterTool extends BaseTool {
async getCharacterOcid(characterName, context) {
try {
const result = await context.nexonClient.getCharacterOcid(characterName);
return result.ocid;
}
catch (error) {
this.handleApiError(error, 'Character lookup');
}
}
}
exports.CharacterTool = CharacterTool;
/**
* Abstract base class for guild-related tools
*/
class GuildTool extends BaseTool {
async getGuildId(guildName, worldName, context) {
try {
const result = await context.nexonClient.getGuildId(guildName, worldName);
return result.oguild_id;
}
catch (error) {
this.handleApiError(error, 'Guild lookup');
}
}
}
exports.GuildTool = GuildTool;
/**
* Tool category enumeration
*/
var ToolCategory;
(function (ToolCategory) {
ToolCategory["CHARACTER"] = "character";
ToolCategory["UNION"] = "union";
ToolCategory["GUILD"] = "guild";
ToolCategory["RANKING"] = "ranking";
ToolCategory["UTILITY"] = "utility";
})(ToolCategory || (exports.ToolCategory = ToolCategory = {}));
/**
* Enhanced base tool class with metadata support
*/
class EnhancedBaseTool extends BaseTool {
}
exports.EnhancedBaseTool = EnhancedBaseTool;
//# sourceMappingURL=base-tool.js.map