Skip to main content
Glama
grovesjosephn

Pokemon MCP Server

markdown.ts6.31 kB
import { ResponseFormatter, PokemonData, PokemonComparisonData, PokemonSearchResults, TypeEffectivenessData, } from './base.js'; import { ToolResponse } from '../types/index.js'; /** * Markdown formatter - implements the current formatting logic * Provides rich text formatting suitable for LLM consumption */ export class MarkdownFormatter extends ResponseFormatter { formatPokemon(pokemon: PokemonData): ToolResponse { const pokemonName = this.capitalizeName(pokemon.name); const totalStats = this.calculateStatsTotal(pokemon.stats); const response = `# ${pokemonName} (#${pokemon.id}) **Basic Info:** - Generation: ${pokemon.generation} - Height: ${this.formatHeight(pokemon.height)} - Weight: ${this.formatWeight(pokemon.weight)} - Base Experience: ${pokemon.base_experience} **Types:** ${pokemon.types.map((t) => t.name).join(', ')} **Abilities:** ${pokemon.abilities.map((a) => a.name + (a.is_hidden ? ' (Hidden)' : '')).join(', ')} **Base Stats:** ${pokemon.stats.map((s) => `- ${s.stat_name}: ${s.base_stat}`).join('\n')} - **Total: ${totalStats}**`; return { content: [ { type: 'text', text: response, }, ], }; } formatComparison(comparison: PokemonComparisonData): ToolResponse { const { pokemon1, pokemon2 } = comparison; const pokemon1Name = this.capitalizeName(pokemon1.name); const pokemon2Name = this.capitalizeName(pokemon2.name); const comparisonText = `# Pokemon Comparison ## ${pokemon1Name} vs ${pokemon2Name} | Attribute | ${pokemon1Name} | ${pokemon2Name} | |-----------|${'-'.repeat(pokemon1Name.length)}|${'-'.repeat(pokemon2Name.length)}| | ID | #${pokemon1.id} | #${pokemon2.id} | | Generation | ${pokemon1.generation} | ${pokemon2.generation} | | Height | ${this.formatHeight(pokemon1.height)} | ${this.formatHeight(pokemon2.height)} | | Weight | ${this.formatWeight(pokemon1.weight)} | ${this.formatWeight(pokemon2.weight)} | ## Stat Comparison | Stat | ${pokemon1Name} | ${pokemon2Name} | Difference | |------|${'-'.repeat(pokemon1Name.length)}|${'-'.repeat(pokemon2Name.length)}|------------| ${pokemon1.stats .map((stat) => { const stat2 = pokemon2.stats.find((s) => s.stat_name === stat.stat_name); const diff = stat.base_stat - (stat2?.base_stat ?? 0); const diffStr = diff > 0 ? `+${diff}` : diff.toString(); return `| ${stat.stat_name} | ${stat.base_stat} | ${stat2?.base_stat ?? 0} | ${diffStr} |`; }) .join('\n')} **Total Stats:** ${this.calculateStatsTotal(pokemon1.stats)} vs ${this.calculateStatsTotal(pokemon2.stats)}`; return { content: [ { type: 'text', text: comparisonText, }, ], }; } formatSearchResults(results: PokemonSearchResults): ToolResponse { if (results.results.length === 0) { return this.formatError('No Pokemon found matching the criteria.'); } const resultsText = `# Search Results (${results.totalCount} found) ${results.results .map((pokemon) => { const pokemonName = this.capitalizeName(pokemon.name); return `**${pokemonName}** (#${pokemon.id}) - Gen ${pokemon.generation} Types: ${pokemon.types.join(', ')}`; }) .join('\n\n')}`; return { content: [ { type: 'text', text: resultsText, }, ], }; } formatTypeEffectiveness(data: TypeEffectivenessData): ToolResponse { const typeName = this.capitalizeName(data.typeName); let result = `# ${typeName} Type Analysis\n\n`; if (data.includePokemon && data.pokemonList.length > 0) { result += `## Pokemon with ${typeName.toLowerCase()} type (showing first 20):\n\n`; result += data.pokemonList .map( (p) => `- **${this.capitalizeName(p.name)}** (#${p.id}) - Gen ${p.generation}` ) .join('\n'); } return { content: [ { type: 'text', text: result, }, ], }; } formatPokemonStats(pokemon: PokemonData): ToolResponse { const pokemonName = this.capitalizeName(pokemon.name); const totalStats = this.calculateStatsTotal(pokemon.stats); const statsText = `# ${pokemonName} - Detailed Stats ## Base Stats Breakdown ${pokemon.stats .map((stat) => { const percentage = Math.round((stat.base_stat / 255) * 100); // Max stat is typically 255 const bar = '█'.repeat(Math.floor(percentage / 5)) + '░'.repeat(20 - Math.floor(percentage / 5)); return `**${stat.stat_name.toUpperCase()}:** ${stat.base_stat} ${bar} (${percentage}%) *EV Yield: ${stat.effort}*`; }) .join('\n\n')} ## Summary - **Total Base Stats:** ${totalStats} - **Average Stat:** ${Math.round(totalStats / pokemon.stats.length)} - **Highest Stat:** ${pokemon.stats.reduce((max, stat) => (stat.base_stat > max.base_stat ? stat : max)).stat_name} (${Math.max(...pokemon.stats.map((s) => s.base_stat))}) - **Lowest Stat:** ${pokemon.stats.reduce((min, stat) => (stat.base_stat < min.base_stat ? stat : min)).stat_name} (${Math.min(...pokemon.stats.map((s) => s.base_stat))})`; return { content: [ { type: 'text', text: statsText, }, ], }; } formatStrongestPokemon(data: StrongestPokemonData): ToolResponse { if (data.results.length === 0) { return this.formatError( `No Pokemon found for criteria: ${data.criteria.criteria}` ); } const criteriaFormatted = data.criteria.criteria.replace('_', ' '); const resultText = `# Strongest Pokemon by ${criteriaFormatted} ${data.results .map( (p, index) => `${index + 1}. **${this.capitalizeName(p.name)}** (#${p.id}) - Gen ${p.generation} ${criteriaFormatted}: ${p.statValue}` ) .join('\n\n')}`; return { content: [ { type: 'text', text: resultText, }, ], }; } formatError(message: string): ToolResponse { return { content: [ { type: 'text', text: `❌ **Error:** ${message}`, }, ], }; } formatNotFound(identifier: string): ToolResponse { return { content: [ { type: 'text', text: `Pokemon "${identifier}" not found.`, }, ], }; } }

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