Skip to main content
Glama
grovesjosephn

Pokemon MCP Server

json.ts8.35 kB
import { ResponseFormatter, PokemonData, PokemonComparisonData, PokemonSearchResults, TypeEffectivenessData, } from './base.js'; import { ToolResponse } from '../types/index.js'; /** * JSON formatter - provides structured data output * Useful for programmatic consumption or when structured data is preferred */ export class JsonFormatter extends ResponseFormatter { formatPokemon(pokemon: PokemonData): ToolResponse { const totalStats = this.calculateStatsTotal(pokemon.stats); const structuredData = { id: pokemon.id, name: this.capitalizeName(pokemon.name), basic_info: { generation: pokemon.generation, height_meters: pokemon.height / 10, weight_kg: pokemon.weight / 10, base_experience: pokemon.base_experience, }, types: pokemon.types.map((t) => t.name), abilities: pokemon.abilities.map((a) => ({ name: a.name, is_hidden: a.is_hidden, slot: a.slot, })), stats: { individual: pokemon.stats.reduce( (acc, stat) => { acc[stat.stat_name] = { base_stat: stat.base_stat, effort: stat.effort, }; return acc; }, {} as Record<string, { base_stat: number; effort: number }> ), total: totalStats, average: Math.round(totalStats / pokemon.stats.length), }, urls: { species: pokemon.species_url, sprite: pokemon.sprite_url, }, }; return { content: [ { type: 'text', text: `# ${this.capitalizeName(pokemon.name)} Data\n\n\`\`\`json\n${JSON.stringify(structuredData, null, 2)}\n\`\`\``, }, ], }; } formatComparison(comparison: PokemonComparisonData): ToolResponse { const { pokemon1, pokemon2 } = comparison; const comparisonData = { comparison: { pokemon1: { id: pokemon1.id, name: this.capitalizeName(pokemon1.name), generation: pokemon1.generation, height_meters: pokemon1.height / 10, weight_kg: pokemon1.weight / 10, total_stats: this.calculateStatsTotal(pokemon1.stats), }, pokemon2: { id: pokemon2.id, name: this.capitalizeName(pokemon2.name), generation: pokemon2.generation, height_meters: pokemon2.height / 10, weight_kg: pokemon2.weight / 10, total_stats: this.calculateStatsTotal(pokemon2.stats), }, stat_differences: pokemon1.stats.map((stat) => { const stat2 = pokemon2.stats.find( (s) => s.stat_name === stat.stat_name ); return { stat_name: stat.stat_name, pokemon1_value: stat.base_stat, pokemon2_value: stat2?.base_stat || 0, difference: stat.base_stat - (stat2?.base_stat || 0), }; }), summary: { stronger_pokemon: this.calculateStatsTotal(pokemon1.stats) > this.calculateStatsTotal(pokemon2.stats) ? this.capitalizeName(pokemon1.name) : this.capitalizeName(pokemon2.name), total_stats_difference: this.calculateStatsTotal(pokemon1.stats) - this.calculateStatsTotal(pokemon2.stats), }, }, }; return { content: [ { type: 'text', text: `# Pokemon Comparison Data\n\n\`\`\`json\n${JSON.stringify(comparisonData, null, 2)}\n\`\`\``, }, ], }; } formatSearchResults(results: PokemonSearchResults): ToolResponse { if (results.results.length === 0) { return this.formatError('No Pokemon found matching the criteria.'); } const searchData = { search_results: { total_found: results.totalCount, criteria: results.criteria, results: results.results.map((pokemon) => ({ id: pokemon.id, name: this.capitalizeName(pokemon.name), generation: pokemon.generation, types: pokemon.types, })), }, }; return { content: [ { type: 'text', text: `# Pokemon Search Results\n\n\`\`\`json\n${JSON.stringify(searchData, null, 2)}\n\`\`\``, }, ], }; } formatTypeEffectiveness(data: TypeEffectivenessData): ToolResponse { const effectivenessData = { type_analysis: { type: this.capitalizeName(data.typeName), include_pokemon: data.includePokemon, pokemon_with_type: data.pokemonList.map((pokemon) => ({ id: pokemon.id, name: this.capitalizeName(pokemon.name), generation: pokemon.generation, })), }, }; return { content: [ { type: 'text', text: `# ${this.capitalizeName(data.type)} Type Effectiveness Data\n\n\`\`\`json\n${JSON.stringify(effectivenessData, null, 2)}\n\`\`\``, }, ], }; } formatPokemonStats(pokemon: PokemonData): ToolResponse { const totalStats = this.calculateStatsTotal(pokemon.stats); const statsArray = pokemon.stats.map((s) => s.base_stat); const statsData = { pokemon_stats: { pokemon: { id: pokemon.id, name: this.capitalizeName(pokemon.name), }, stats: { individual: pokemon.stats.reduce( (acc, stat) => { acc[stat.stat_name] = { base_stat: stat.base_stat, effort_value_yield: stat.effort, percentage_of_max: Math.round((stat.base_stat / 255) * 100), // Assuming 255 is max }; return acc; }, {} as Record<string, any> ), summary: { total: totalStats, average: Math.round(totalStats / pokemon.stats.length), highest: { stat: pokemon.stats.reduce((max, stat) => stat.base_stat > max.base_stat ? stat : max ).stat_name, value: Math.max(...statsArray), }, lowest: { stat: pokemon.stats.reduce((min, stat) => stat.base_stat < min.base_stat ? stat : min ).stat_name, value: Math.min(...statsArray), }, }, }, }, }; return { content: [ { type: 'text', text: `# ${this.capitalizeName(pokemon.name)} Stats Data\n\n\`\`\`json\n${JSON.stringify(statsData, null, 2)}\n\`\`\``, }, ], }; } formatStrongestPokemon(data: StrongestPokemonData): ToolResponse { if (data.results.length === 0) { return this.formatError( `No Pokemon found for criteria: ${data.criteria.criteria}` ); } const strongestData = { strongest_pokemon: { criteria: data.criteria.criteria.replace('_', ' ').toUpperCase(), results: data.results.map((pokemon, index) => ({ rank: index + 1, pokemon: { id: pokemon.id, name: this.capitalizeName(pokemon.name), generation: pokemon.generation, }, criteria_value: pokemon.statValue, })), }, }; return { content: [ { type: 'text', text: `# Strongest Pokemon by ${data.criteria.criteria.replace('_', ' ').toUpperCase()}\n\n\`\`\`json\n${JSON.stringify(strongestData, null, 2)}\n\`\`\``, }, ], }; } formatError(message: string): ToolResponse { const errorData = { error: { message: message, timestamp: new Date().toISOString(), }, }; return { content: [ { type: 'text', text: `# Error\n\n\`\`\`json\n${JSON.stringify(errorData, null, 2)}\n\`\`\``, }, ], }; } formatNotFound(identifier: string): ToolResponse { const notFoundData = { not_found: { searched_for: identifier, message: `Pokemon "${identifier}" not found.`, timestamp: new Date().toISOString(), }, }; return { content: [ { type: 'text', text: `# Pokemon Not Found\n\n\`\`\`json\n${JSON.stringify(notFoundData, null, 2)}\n\`\`\``, }, ], }; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/grovesjosephn/pokemcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server