maplestory-mcp-server
Version:
Official-style NEXON MapleStory MCP Server for Claude Desktop - Complete character info, union details, guild data, rankings, and game mechanics
345 lines • 14.4 kB
JavaScript
;
/**
* Union Information Tools for MCP Maple
* Provides MCP tools for retrieving MapleStory union data and rankings
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.GetUnionRankingTool = exports.GetUnionRaiderTool = exports.GetUnionInfoTool = void 0;
const base_tool_1 = require("./base-tool");
/**
* Tool for getting union information
*/
class GetUnionInfoTool extends base_tool_1.EnhancedBaseTool {
name = 'get_union_info';
description = 'Retrieve union information for a MapleStory character including level, grade, and artifact details';
inputSchema = {
type: 'object',
properties: {
characterName: {
type: 'string',
description: 'The name of the character to look up union info for',
minLength: 1,
maxLength: 12,
pattern: '^[a-zA-Z0-9가-힣]+$',
},
date: {
type: 'string',
description: 'Date for union info in YYYY-MM-DD format (optional, defaults to yesterday)',
pattern: '^\\d{4}-\\d{2}-\\d{2}$',
},
},
required: ['characterName'],
additionalProperties: false,
};
metadata = {
category: base_tool_1.ToolCategory.UNION,
tags: ['union', 'level', 'grade', 'artifact'],
examples: [
{
description: 'Get union info for character',
arguments: { characterName: '스카니아용사' },
},
{
description: 'Get union info for specific date',
arguments: { characterName: '스카니아용사', date: '2024-01-15' },
},
],
};
async executeImpl(args, context) {
const characterName = this.getRequiredString(args, 'characterName');
const date = this.getOptionalString(args, 'date');
try {
const startTime = Date.now();
// Get character OCID first
context.logger.info('Looking up character OCID for union info', { characterName });
const ocidResult = await context.nexonClient.getCharacterOcid(characterName);
const ocid = ocidResult.ocid;
// Get union info
context.logger.info('Fetching union information', { characterName, ocid });
const unionInfo = await context.nexonClient.getUnionInfo(ocid, date);
const executionTime = Date.now() - startTime;
context.logger.info('Union info retrieved successfully', {
characterName,
unionLevel: unionInfo.union_level,
unionGrade: unionInfo.union_grade,
artifactLevel: unionInfo.union_artifact_level,
executionTime,
});
return this.formatResult({
characterName,
date: unionInfo.date || date || 'latest',
unionLevel: unionInfo.union_level,
unionGrade: unionInfo.union_grade,
unionArtifact: {
level: unionInfo.union_artifact_level,
exp: unionInfo.union_artifact_exp,
point: unionInfo.union_artifact_point,
},
}, {
executionTime,
cacheHit: false,
apiCalls: 2, // OCID lookup + union info
});
}
catch (error) {
context.logger.error('Failed to get union info', {
characterName,
error: error instanceof Error ? error.message : String(error),
});
return this.formatError(`Failed to get union info for character "${characterName}": ${error instanceof Error ? error.message : String(error)}`);
}
}
}
exports.GetUnionInfoTool = GetUnionInfoTool;
/**
* Tool for getting union raider information
*/
class GetUnionRaiderTool extends base_tool_1.EnhancedBaseTool {
name = 'get_union_raider';
description = 'Retrieve union raider board information including block placement and stats';
inputSchema = {
type: 'object',
properties: {
characterName: {
type: 'string',
description: 'The name of the character to look up union raider for',
minLength: 1,
maxLength: 12,
pattern: '^[a-zA-Z0-9가-힣]+$',
},
date: {
type: 'string',
description: 'Date for union raider in YYYY-MM-DD format (optional, defaults to yesterday)',
pattern: '^\\d{4}-\\d{2}-\\d{2}$',
},
},
required: ['characterName'],
additionalProperties: false,
};
metadata = {
category: base_tool_1.ToolCategory.UNION,
tags: ['union', 'raider', 'blocks', 'stats', 'board'],
examples: [
{
description: 'Get union raider info for character',
arguments: { characterName: '스카니아용사' },
},
{
description: 'Get union raider for specific date',
arguments: { characterName: '스카니아용사', date: '2024-01-15' },
},
],
};
async executeImpl(args, context) {
const characterName = this.getRequiredString(args, 'characterName');
const date = this.getOptionalString(args, 'date');
try {
const startTime = Date.now();
// Get character OCID first
context.logger.info('Looking up character OCID for union raider', { characterName });
const ocidResult = await context.nexonClient.getCharacterOcid(characterName);
const ocid = ocidResult.ocid;
// Get union raider info
context.logger.info('Fetching union raider information', { characterName, ocid });
const raiderInfo = await context.nexonClient.getUnionRaider(ocid, date);
const executionTime = Date.now() - startTime;
// Process union blocks for better presentation
const blocksByClass = raiderInfo.union_block?.reduce((acc, block) => {
if (!acc[block.block_class]) {
acc[block.block_class] = [];
}
acc[block.block_class].push({
type: block.block_type,
level: block.block_level,
controlPoint: block.block_control_point,
positions: block.block_position,
});
return acc;
}, {}) || {};
context.logger.info('Union raider info retrieved successfully', {
characterName,
blockCount: raiderInfo.union_block?.length || 0,
innerStatCount: raiderInfo.union_inner_stat?.length || 0,
executionTime,
});
return this.formatResult({
characterName,
date: raiderInfo.date || date || 'latest',
presetNo: raiderInfo.use_preset_no,
raiderStats: raiderInfo.union_raider_stat || [],
occupiedStats: raiderInfo.union_occupied_stat || [],
innerStats: raiderInfo.union_inner_stat?.map((stat) => ({
fieldId: stat.stat_field_id,
effect: stat.stat_field_effect,
})) || [],
blocks: {
total: raiderInfo.union_block?.length || 0,
byClass: blocksByClass,
details: raiderInfo.union_block || [],
},
}, {
executionTime,
cacheHit: false,
apiCalls: 2, // OCID lookup + raider info
});
}
catch (error) {
context.logger.error('Failed to get union raider info', {
characterName,
error: error instanceof Error ? error.message : String(error),
});
return this.formatError(`Failed to get union raider info for character "${characterName}": ${error instanceof Error ? error.message : String(error)}`);
}
}
}
exports.GetUnionRaiderTool = GetUnionRaiderTool;
/**
* Tool for getting union ranking
*/
class GetUnionRankingTool extends base_tool_1.EnhancedBaseTool {
name = 'get_union_ranking';
description = 'Retrieve union power rankings for a specific world or overall rankings';
inputSchema = {
type: 'object',
properties: {
worldName: {
type: 'string',
description: 'World name to get rankings for (optional, gets all worlds if not specified)',
enum: [
'스카니아',
'베라',
'루나',
'제니스',
'크로아',
'유니온',
'엘리시움',
'이노시스',
'레드',
'오로라',
'아케인',
'노바',
'리부트',
'리부트2',
],
},
characterName: {
type: 'string',
description: 'Specific character name to search for in rankings (optional)',
minLength: 1,
maxLength: 12,
pattern: '^[a-zA-Z0-9가-힣]+$',
},
page: {
type: 'integer',
description: 'Page number for pagination (1-based, optional, defaults to 1)',
minimum: 1,
maximum: 200,
default: 1,
},
date: {
type: 'string',
description: 'Date for rankings in YYYY-MM-DD format (optional, defaults to yesterday)',
pattern: '^\\d{4}-\\d{2}-\\d{2}$',
},
},
additionalProperties: false,
};
metadata = {
category: base_tool_1.ToolCategory.UNION,
tags: ['union', 'ranking', 'power', 'leaderboard'],
examples: [
{
description: 'Get union rankings for all worlds',
arguments: {},
},
{
description: 'Get union rankings for specific world',
arguments: { worldName: '스카니아' },
},
{
description: 'Get union rankings for specific character',
arguments: { characterName: '스카니아용사' },
},
{
description: 'Get page 2 of union rankings',
arguments: { worldName: '스카니아', page: 2 },
},
],
};
async executeImpl(args, context) {
const worldName = this.getOptionalString(args, 'worldName');
const characterName = this.getOptionalString(args, 'characterName');
const page = this.getOptionalNumber(args, 'page', 1);
const date = this.getOptionalString(args, 'date');
try {
const startTime = Date.now();
let ocid;
// If character name is provided, get OCID for search
if (characterName) {
context.logger.info('Looking up character OCID for union ranking search', {
characterName,
});
const ocidResult = await context.nexonClient.getCharacterOcid(characterName);
ocid = ocidResult.ocid;
}
// Get union rankings
context.logger.info('Fetching union rankings', {
worldName: worldName || undefined,
characterName: characterName || undefined,
ocid: ocid ? `${ocid.substring(0, 8)}...` : undefined,
page,
});
const rankings = await context.nexonClient.getUnionRanking(worldName, ocid, page, date);
const executionTime = Date.now() - startTime;
const rankingData = rankings.ranking?.map((entry) => ({
rank: entry.ranking,
characterName: entry.character_name,
world: entry.world_name,
class: entry.class_name,
subClass: entry.sub_class_name,
unionLevel: entry.union_level,
unionPower: entry.union_power,
date: entry.date,
})) || [];
context.logger.info('Union rankings retrieved successfully', {
worldName: worldName || undefined,
characterName: characterName || undefined,
page,
resultsCount: rankingData.length,
executionTime,
});
return this.formatResult({
page,
pageSize: rankingData.length,
worldName: worldName || 'all',
searchCharacter: characterName || undefined,
date: date || 'latest',
rankings: rankingData,
summary: {
totalResults: rankingData.length,
topUnionLevel: rankingData.length > 0 ? Math.max(...rankingData.map((r) => r.unionLevel)) : 0,
topUnionPower: rankingData.length > 0 ? Math.max(...rankingData.map((r) => r.unionPower)) : 0,
worldDistribution: rankingData.reduce((acc, entry) => {
acc[entry.world] = (acc[entry.world] || 0) + 1;
return acc;
}, {}),
},
}, {
executionTime,
cacheHit: false,
apiCalls: characterName ? 2 : 1, // OCID lookup (if needed) + rankings
});
}
catch (error) {
context.logger.error('Failed to get union rankings', {
worldName: worldName || undefined,
characterName: characterName || undefined,
page,
error: error instanceof Error ? error.message : String(error),
});
return this.formatError(`Failed to get union rankings: ${error instanceof Error ? error.message : String(error)}`);
}
}
}
exports.GetUnionRankingTool = GetUnionRankingTool;
//# sourceMappingURL=union-tools.js.map