@champz-llc/legends-mcp-server 1.3.6 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +116 -52
- package/package.json +3 -2
package/index.js
CHANGED
|
@@ -7,8 +7,9 @@ import {
|
|
|
7
7
|
ListToolsRequestSchema,
|
|
8
8
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
9
9
|
import fetch from 'node-fetch';
|
|
10
|
+
import sharp from 'sharp';
|
|
10
11
|
|
|
11
|
-
// Helper function to fetch image and convert to base64
|
|
12
|
+
// Helper function to fetch image, resize, and convert to base64
|
|
12
13
|
async function fetchImageAsBase64(imageUrl) {
|
|
13
14
|
try {
|
|
14
15
|
console.error(`[MCP] Fetching image: ${imageUrl}`);
|
|
@@ -21,12 +22,25 @@ async function fetchImageAsBase64(imageUrl) {
|
|
|
21
22
|
const contentType = response.headers.get('content-type');
|
|
22
23
|
console.error(`[MCP] Image content-type: ${contentType}`);
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
25
|
+
// Fetch image as buffer
|
|
26
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
27
|
+
const originalBuffer = Buffer.from(arrayBuffer);
|
|
28
|
+
console.error(`[MCP] Original image size: ${Math.round(originalBuffer.length / 1024)}KB`);
|
|
29
|
+
|
|
30
|
+
// Resize image to max 200x200 (perfect for chat) and convert to JPEG for smaller size
|
|
31
|
+
const resizedBuffer = await sharp(originalBuffer)
|
|
32
|
+
.resize(200, 200, {
|
|
33
|
+
fit: 'inside',
|
|
34
|
+
withoutEnlargement: true
|
|
35
|
+
})
|
|
36
|
+
.jpeg({ quality: 80, mozjpeg: true }) // JPEG is much smaller than PNG
|
|
37
|
+
.toBuffer();
|
|
38
|
+
|
|
39
|
+
const base64 = resizedBuffer.toString('base64');
|
|
40
|
+
console.error(`[MCP] Resized image size: ${Math.round(resizedBuffer.length / 1024)}KB, base64: ${Math.round(base64.length / 1024)}KB`);
|
|
27
41
|
return base64;
|
|
28
42
|
} catch (error) {
|
|
29
|
-
console.error(`[MCP] Error
|
|
43
|
+
console.error(`[MCP] Error processing image ${imageUrl}:`, error.message);
|
|
30
44
|
return null;
|
|
31
45
|
}
|
|
32
46
|
}
|
|
@@ -645,39 +659,50 @@ You can still ask about:
|
|
|
645
659
|
const stats = data.statistics;
|
|
646
660
|
const claims = data.claims;
|
|
647
661
|
|
|
648
|
-
let output =
|
|
649
|
-
output +=
|
|
650
|
-
output += `Wallet: ${data.wallet}\n`;
|
|
662
|
+
let output = `🍄 **LEGENDS OF CHAMPZ** - Player Stats 🍄\n\n`;
|
|
663
|
+
output += `👤 **Player:** ${displayName}\n`;
|
|
651
664
|
if (data.basename) {
|
|
652
|
-
output +=
|
|
665
|
+
output += `🎯 **Basename:** ${data.basename}\n`;
|
|
653
666
|
}
|
|
654
|
-
output +=
|
|
655
|
-
|
|
656
|
-
output +=
|
|
657
|
-
output +=
|
|
658
|
-
output +=
|
|
659
|
-
output += `
|
|
660
|
-
output += `
|
|
661
|
-
|
|
662
|
-
output +=
|
|
663
|
-
|
|
664
|
-
output +=
|
|
665
|
-
output +=
|
|
666
|
-
output +=
|
|
667
|
-
output += `
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
output += `
|
|
671
|
-
output += `
|
|
672
|
-
output += `
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
output +=
|
|
676
|
-
output +=
|
|
677
|
-
output +=
|
|
678
|
-
output += `
|
|
679
|
-
output += `
|
|
680
|
-
output += `
|
|
667
|
+
output += `📅 **Member Since:** ${new Date(stats.member_since).toLocaleDateString()} - Let's go! 🎮\n\n`;
|
|
668
|
+
|
|
669
|
+
output += `━━━━━━━━━━━━━━━━━━━━━━\n`;
|
|
670
|
+
output += `📦 **PACKS & LEGENDS**\n`;
|
|
671
|
+
output += `━━━━━━━━━━━━━━━━━━━━━━\n`;
|
|
672
|
+
output += ` 🎲 Packs opened: **${stats.total_packs_opened}** ${stats.total_packs_opened > 50 ? '(Pack master! 🔥)' : ''}\n`;
|
|
673
|
+
output += ` 💎 CHAMPZ spent: **${stats.champz_spent_on_packs.toLocaleString()}** tokens\n`;
|
|
674
|
+
output += ` 🍄 Legends owned: **${stats.legends_owned}** ${stats.legends_owned > 30 ? '(Epic collection! ⭐)' : ''}\n`;
|
|
675
|
+
output += ` ⭐ Trainer slots: **${stats.saved_trainer_slots}**\n\n`;
|
|
676
|
+
|
|
677
|
+
output += `━━━━━━━━━━━━━━━━━━━━━━\n`;
|
|
678
|
+
output += `⚔️ **BATTLE RECORD**\n`;
|
|
679
|
+
output += `━━━━━━━━━━━━━━━━━━━━━━\n`;
|
|
680
|
+
output += ` 🎯 Total battles: **${stats.total_battles}** fights!\n`;
|
|
681
|
+
const winRate = (stats.win_rate * 100).toFixed(1);
|
|
682
|
+
const winRateEmoji = winRate >= 70 ? '🔥🔥🔥' : winRate >= 60 ? '🔥🔥' : winRate >= 50 ? '🔥' : '💪';
|
|
683
|
+
output += ` 🏆 Wins: **${stats.battles_won}** (${winRate}% win rate ${winRateEmoji})\n`;
|
|
684
|
+
output += ` 💀 Losses: **${stats.battles_lost}**\n`;
|
|
685
|
+
output += ` ⚡ Current streak: **${stats.current_win_streak}** ${stats.current_win_streak >= 5 ? '(ON FIRE! 🔥)' : ''}\n`;
|
|
686
|
+
output += ` 🌟 Best streak: **${stats.best_win_streak}** ${stats.best_win_streak >= 10 ? '(Legendary! 💎)' : ''}\n\n`;
|
|
687
|
+
|
|
688
|
+
output += `━━━━━━━━━━━━━━━━━━━━━━\n`;
|
|
689
|
+
output += `👑 **THRONES & GUARDIAN**\n`;
|
|
690
|
+
output += `━━━━━━━━━━━━━━━━━━━━━━\n`;
|
|
691
|
+
output += ` 🏆 Thrones owned: **${stats.thrones_owned}** ${stats.thrones_owned > 0 ? '(Champion! 👑)' : ''}\n`;
|
|
692
|
+
output += ` 🛡️ Times held guardian: **${stats.times_held_guardian}** ${stats.times_held_guardian > 5 ? '(Guardian master! ⚡)' : ''}\n`;
|
|
693
|
+
output += ` 💰 CHAMPZ spent: **${stats.champz_spent_on_guardian.toLocaleString()}** tokens\n\n`;
|
|
694
|
+
|
|
695
|
+
output += `━━━━━━━━━━━━━━━━━━━━━━\n`;
|
|
696
|
+
output += `💵 **REWARDS CLAIMED**\n`;
|
|
697
|
+
output += `━━━━━━━━━━━━━━━━━━━━━━\n`;
|
|
698
|
+
const totalUSDC = claims.total_usdc_claimed;
|
|
699
|
+
const totalCHAMPZ = claims.total_champz_claimed;
|
|
700
|
+
output += ` 💵 Total USDC: **$${totalUSDC}** ${totalUSDC > 50 ? '(Big earner! 💰)' : totalUSDC > 20 ? '(Nice! 🎯)' : ''}\n`;
|
|
701
|
+
output += ` 🍄 Total CHAMPZ: **${totalCHAMPZ.toLocaleString()}** tokens ${totalCHAMPZ > 10000 ? '(Whale alert! 🐋)' : ''}\n`;
|
|
702
|
+
if (claims.by_type['6'].count > 0 || claims.by_type['19'].count > 0) {
|
|
703
|
+
output += ` 🎉 You're earning rewards - keep battling! ⚔️\n`;
|
|
704
|
+
}
|
|
705
|
+
output += `\n`;
|
|
681
706
|
|
|
682
707
|
// Build content array with text and images
|
|
683
708
|
const content = [
|
|
@@ -806,17 +831,45 @@ You can still ask about:
|
|
|
806
831
|
};
|
|
807
832
|
}
|
|
808
833
|
|
|
809
|
-
// Build output
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
834
|
+
// Build card-like output with gaming vibes
|
|
835
|
+
const rarityEmojis = {
|
|
836
|
+
unique: '💎',
|
|
837
|
+
legendary: '🌟',
|
|
838
|
+
epic: '🟣',
|
|
839
|
+
rare: '🔵',
|
|
840
|
+
common: '⚪'
|
|
841
|
+
};
|
|
842
|
+
const elementEmojis = {
|
|
843
|
+
fire: '🔥',
|
|
844
|
+
water: '💧',
|
|
845
|
+
wind: '🌪️',
|
|
846
|
+
earth: '🌍',
|
|
847
|
+
light: '✨',
|
|
848
|
+
dark: '🌑'
|
|
849
|
+
};
|
|
817
850
|
|
|
818
|
-
|
|
851
|
+
let output = `╔════════════════════════╗\n`;
|
|
852
|
+
output += `║ ${rarityEmojis[legend.rarity]} ${legend.rarity.toUpperCase()} LEGEND #${legend.legend_id} ║\n`;
|
|
853
|
+
output += `╚════════════════════════╝\n\n`;
|
|
854
|
+
|
|
855
|
+
output += `🍄 **${legend.name}**\n\n`;
|
|
856
|
+
|
|
857
|
+
// Elements with emojis
|
|
858
|
+
const elementIcons = legend.elements.map(e => `${elementEmojis[e] || '⭐'} ${e.charAt(0).toUpperCase() + e.slice(1)}`).join(' ');
|
|
859
|
+
output += `${elementIcons}\n\n`;
|
|
860
|
+
|
|
861
|
+
output += `⚡ **Total Power:** ${legend.total_power}\n`;
|
|
862
|
+
output += `⚔️ **ATK:** ${legend.attack}\n`;
|
|
863
|
+
output += `🛡️ **DEF:** ${legend.defense}\n`;
|
|
864
|
+
output += `💨 **SPD:** ${legend.speed}\n\n`;
|
|
865
|
+
|
|
866
|
+
output += `📅 Rolled: ${new Date(legend.rolled_at).toLocaleDateString()}\n`;
|
|
867
|
+
output += legend.is_saved ? `⭐ **Saved Trainer** - This legend is in your collection!\n` : `💡 Not saved yet - save this legend to keep it forever!\n`;
|
|
868
|
+
|
|
869
|
+
// Fetch image
|
|
819
870
|
const imageUrl = `https://img.champz.world${legend.image_path}`;
|
|
871
|
+
|
|
872
|
+
// Fetch and convert image to base64
|
|
820
873
|
const base64Data = await fetchImageAsBase64(imageUrl);
|
|
821
874
|
|
|
822
875
|
const content = [
|
|
@@ -830,7 +883,7 @@ You can still ask about:
|
|
|
830
883
|
content.push({
|
|
831
884
|
type: 'image',
|
|
832
885
|
data: base64Data,
|
|
833
|
-
mimeType: 'image/
|
|
886
|
+
mimeType: 'image/jpeg',
|
|
834
887
|
});
|
|
835
888
|
}
|
|
836
889
|
|
|
@@ -882,11 +935,22 @@ You can still ask about:
|
|
|
882
935
|
};
|
|
883
936
|
}
|
|
884
937
|
|
|
885
|
-
// Build output
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
938
|
+
// Build card-like output with gaming vibes
|
|
939
|
+
const rarityEmojis = {
|
|
940
|
+
legendary: '👑',
|
|
941
|
+
epic: '💜',
|
|
942
|
+
rare: '💙',
|
|
943
|
+
common: '🤍'
|
|
944
|
+
};
|
|
945
|
+
|
|
946
|
+
let output = `╔════════════════════════╗\n`;
|
|
947
|
+
output += `║ ${rarityEmojis[throne.rarity] || '🏆'} ${throne.rarity.toUpperCase()} THRONE #${throne.throne_id} ║\n`;
|
|
948
|
+
output += `╚════════════════════════╝\n\n`;
|
|
949
|
+
|
|
950
|
+
output += `👑 **${throne.name}**\n\n`;
|
|
951
|
+
output += `🎮 **Earned in Cycle:** ${throne.cycle_id}\n`;
|
|
952
|
+
output += `📅 **Date Earned:** ${new Date(throne.earned_at).toLocaleDateString()}\n\n`;
|
|
953
|
+
output += `🏆 You're a champion! This throne proves you held the Guardian position and won the cycle!\n`;
|
|
890
954
|
|
|
891
955
|
// Fetch and convert image to base64
|
|
892
956
|
const imageUrl = `https://img.champz.world${throne.image_path}`;
|
|
@@ -903,7 +967,7 @@ You can still ask about:
|
|
|
903
967
|
content.push({
|
|
904
968
|
type: 'image',
|
|
905
969
|
data: base64Data,
|
|
906
|
-
mimeType: 'image/
|
|
970
|
+
mimeType: 'image/jpeg',
|
|
907
971
|
});
|
|
908
972
|
}
|
|
909
973
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@champz-llc/legends-mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "MCP server for Legends of Champz - Query game stats, access personal data with signature auth, and claim rewards through Claude Desktop",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
37
|
-
"node-fetch": "^3.3.2"
|
|
37
|
+
"node-fetch": "^3.3.2",
|
|
38
|
+
"sharp": "^0.34.5"
|
|
38
39
|
}
|
|
39
40
|
}
|