Skip to main content
Glama
index.ts29.1 kB
#!/usr/bin/env node import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; // ============================================ // CONFIGURACIÓN // ============================================ const API_BASE_URL = "https://api-colombia.com/api/v1"; const server = new McpServer({ name: "colombia-mcp-server", version: "1.0.0", }); // ============================================ // CLIENTE API // ============================================ async function apiRequest<T>(endpoint: string): Promise<T> { const url = `${API_BASE_URL}${endpoint}`; const response = await fetch(url, { method: "GET", headers: { "Accept": "application/json", "Content-Type": "application/json", }, }); if (!response.ok) { throw new Error(`API Error: ${response.status} ${response.statusText}`); } return response.json() as Promise<T>; } // ============================================ // TIPOS // ============================================ interface Region { id: number; name: string; description: string; } interface Department { id: number; name: string; description: string; cityCapitalId: number; municipalities: number; surface: number; population: number; phonePrefix: string; regionId: number; cityCapital?: { id: number; name: string; description: string; }; } interface City { id: number; name: string; description: string; surface: number | null; population: number | null; postalCode: string | null; departmentId: number; } interface TouristAttraction { id: number; name: string; description: string; images: string[]; latitude: string; longitude: string; cityId: number; city?: City; } // ============================================ // HERRAMIENTAS // ============================================ // 1. Obtener todas las regiones server.registerTool( "get_regions", { title: "Obtener Regiones de Colombia", description: `Obtiene las 6 regiones naturales de Colombia: Caribe, Pacífico, Orinoquía, Amazonía, Andina e Insular. Returns: Lista de regiones con id, nombre y descripción. Ejemplo de uso: - "¿Cuáles son las regiones de Colombia?" - "Dame información sobre las regiones naturales"`, inputSchema: {}, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async () => { try { const regions = await apiRequest<Region[]>("/Region"); const resultado = regions.map(r => ({ id: r.id, nombre: r.name, descripcion: r.description, })); return { content: [ { type: "text", text: JSON.stringify(resultado, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error al obtener regiones: ${error instanceof Error ? error.message : "Error desconocido"}`, }, ], }; } } ); // 2. Obtener todos los departamentos server.registerTool( "get_departments", { title: "Obtener Departamentos de Colombia", description: `Obtiene los 32 departamentos de Colombia más Bogotá D.C. Returns: Lista de departamentos con: id, nombre, capital, población, superficie y región. Ejemplo de uso: - "¿Cuáles son los departamentos de Colombia?" - "Lista todos los departamentos"`, inputSchema: {}, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async () => { try { const departments = await apiRequest<Department[]>("/Department"); const resultado = departments.map(d => ({ id: d.id, nombre: d.name, capital: d.cityCapital?.name || "N/A", poblacion: d.population, superficie_km2: d.surface, municipios: d.municipalities, region_id: d.regionId, })); return { content: [ { type: "text", text: JSON.stringify(resultado, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error al obtener departamentos: ${error instanceof Error ? error.message : "Error desconocido"}`, }, ], }; } } ); // 3. Obtener departamento por ID o nombre server.registerTool( "get_department", { title: "Obtener Departamento Específico", description: `Obtiene información detallada de un departamento específico por ID o nombre. Args: - id (number, opcional): ID del departamento (1-33) - name (string, opcional): Nombre del departamento (ej: "Antioquia", "Cundinamarca") Returns: Información detallada del departamento incluyendo población, superficie, capital y descripción. Ejemplo de uso: - "Dame información sobre Antioquia" - "¿Cuál es la capital de Cundinamarca?"`, inputSchema: { id: z.number().int().min(1).max(33).optional().describe("ID del departamento (1-33)"), name: z.string().optional().describe("Nombre del departamento"), }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async ({ id, name }) => { try { let department: Department; if (id) { department = await apiRequest<Department>(`/Department/${id}`); } else if (name) { department = await apiRequest<Department>(`/Department/name/${encodeURIComponent(name)}`); } else { return { content: [ { type: "text", text: "Error: Debes proporcionar un ID o nombre del departamento", }, ], }; } const resultado = { id: department.id, nombre: department.name, descripcion: department.description, capital: department.cityCapital?.name || "N/A", poblacion: department.population, superficie_km2: department.surface, municipios: department.municipalities, prefijo_telefonico: department.phonePrefix, region_id: department.regionId, }; return { content: [ { type: "text", text: JSON.stringify(resultado, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error al obtener departamento: ${error instanceof Error ? error.message : "Error desconocido"}`, }, ], }; } } ); // 4. Obtener departamentos por región server.registerTool( "get_departments_by_region", { title: "Obtener Departamentos por Región", description: `Obtiene todos los departamentos que pertenecen a una región específica. Args: - region_id (number): ID de la región - 1 = Caribe - 2 = Pacífico - 3 = Orinoquía - 4 = Amazonía - 5 = Andina - 6 = Insular Returns: Lista de departamentos de esa región. Ejemplo de uso: - "¿Cuáles departamentos están en la región Caribe?" - "Dame los departamentos de la Amazonía"`, inputSchema: { region_id: z.number().int().min(1).max(6).describe("ID de la región (1=Caribe, 2=Pacífico, 3=Orinoquía, 4=Amazonía, 5=Andina, 6=Insular)"), }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async ({ region_id }) => { try { const departments = await apiRequest<Department[]>(`/Region/${region_id}/departments`); const regionNames: Record<number, string> = { 1: "Caribe", 2: "Pacífico", 3: "Orinoquía", 4: "Amazonía", 5: "Andina", 6: "Insular", }; const resultado = { region: regionNames[region_id] || `Región ${region_id}`, total_departamentos: departments.length, departamentos: departments.map(d => ({ id: d.id, nombre: d.name, capital: d.cityCapital?.name || "N/A", poblacion: d.population, })), }; return { content: [ { type: "text", text: JSON.stringify(resultado, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error al obtener departamentos por región: ${error instanceof Error ? error.message : "Error desconocido"}`, }, ], }; } } ); // 5. Obtener ciudades de un departamento server.registerTool( "get_cities", { title: "Obtener Ciudades de un Departamento", description: `Obtiene todas las ciudades/municipios de un departamento específico. Args: - department_id (number): ID del departamento Returns: Lista de ciudades con nombre, población y código postal. Ejemplo de uso: - "¿Qué ciudades hay en Antioquia?" - "Lista los municipios del Valle del Cauca"`, inputSchema: { department_id: z.number().int().min(1).describe("ID del departamento"), }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async ({ department_id }) => { try { const cities = await apiRequest<City[]>(`/Department/${department_id}/cities`); const resultado = { departamento_id: department_id, total_ciudades: cities.length, ciudades: cities.map(c => ({ id: c.id, nombre: c.name, poblacion: c.population, superficie_km2: c.surface, codigo_postal: c.postalCode, })), }; return { content: [ { type: "text", text: JSON.stringify(resultado, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error al obtener ciudades: ${error instanceof Error ? error.message : "Error desconocido"}`, }, ], }; } } ); // 6. Obtener atracciones turísticas server.registerTool( "get_tourist_attractions", { title: "Obtener Atracciones Turísticas", description: `Obtiene atracciones turísticas de Colombia. Puedes buscar por ciudad o por palabra clave. Args: - city_id (number, opcional): ID de la ciudad para filtrar - search (string, opcional): Palabra clave para buscar (ej: "playa", "museo", "parque") Returns: Lista de atracciones con nombre, descripción, ubicación e imágenes. Ejemplo de uso: - "¿Qué lugares turísticos hay en Cartagena?" - "Busca atracciones relacionadas con playas"`, inputSchema: { city_id: z.number().int().optional().describe("ID de la ciudad"), search: z.string().optional().describe("Palabra clave para buscar"), }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async ({ city_id, search }) => { try { let attractions: TouristAttraction[]; if (city_id) { attractions = await apiRequest<TouristAttraction[]>(`/City/${city_id}/touristattractions`); } else if (search) { attractions = await apiRequest<TouristAttraction[]>(`/TouristAttraction/search/${encodeURIComponent(search)}`); } else { attractions = await apiRequest<TouristAttraction[]>("/TouristAttraction"); } const resultado = { total: attractions.length, atracciones: attractions.slice(0, 20).map(a => ({ id: a.id, nombre: a.name, descripcion: a.description, coordenadas: { latitud: a.latitude, longitud: a.longitude, }, imagenes: a.images || [], ciudad_id: a.cityId, })), }; return { content: [ { type: "text", text: JSON.stringify(resultado, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error al obtener atracciones: ${error instanceof Error ? error.message : "Error desconocido"}`, }, ], }; } } ); // 7. Obtener información del país server.registerTool( "get_country_info", { title: "Obtener Información de Colombia", description: `Obtiene información general sobre Colombia como país. Returns: Información del país incluyendo nombre, capital, bandera, moneda, etc. Ejemplo de uso: - "¿Cuál es la capital de Colombia?" - "Dame información general de Colombia"`, inputSchema: {}, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async () => { try { const country = await apiRequest<any>("/Country/Colombia"); const resultado = { nombre: country.name, capital: country.stateCapital, superficie_km2: country.surface, poblacion: country.population, idioma: country.languages, moneda: country.currency, codigo_iso: country.isoCode, codigo_telefono: country.phonePrefix, dominio_internet: country.internetDomain, bandera: country.flags, escudo: country.coatOfArms, himno: country.nationalAnthem, ave_nacional: country.nationalBird, flor_nacional: country.nationalFlower, arbol_nacional: country.nationalTree, }; return { content: [ { type: "text", text: JSON.stringify(resultado, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error al obtener información del país: ${error instanceof Error ? error.message : "Error desconocido"}`, }, ], }; } } ); // 8. Obtener presidentes server.registerTool( "get_presidents", { title: "Obtener Presidentes de Colombia", description: `Obtiene la lista de presidentes de Colombia. Returns: Lista de presidentes con nombre, período, partido político y ciudad de nacimiento. Ejemplo de uso: - "¿Quiénes han sido los presidentes de Colombia?" - "Lista de presidentes colombianos"`, inputSchema: {}, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async () => { try { const presidents = await apiRequest<any[]>("/President"); const resultado = { total: presidents.length, presidentes: presidents.map(p => ({ id: p.id, nombre: p.name, apellido: p.lastName, inicio_periodo: p.startPeriodDate, fin_periodo: p.endPeriodDate, partido_politico: p.politicalParty, descripcion: p.description, imagen: p.image, ciudad_nacimiento_id: p.cityId, })), }; return { content: [ { type: "text", text: JSON.stringify(resultado, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error al obtener presidentes: ${error instanceof Error ? error.message : "Error desconocido"}`, }, ], }; } } ); // 9. Obtener presidente por ID server.registerTool( "get_president", { title: "Obtener Presidente Específico", description: `Obtiene información detallada de un presidente específico. Args: - id (number): ID del presidente Returns: Información detallada del presidente. Ejemplo de uso: - "Dame información sobre el presidente con ID 5"`, inputSchema: { id: z.number().int().min(1).describe("ID del presidente"), }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async ({ id }) => { try { const president = await apiRequest<any>(`/President/${id}`); const resultado = { id: president.id, nombre: president.name, apellido: president.lastName, nombre_completo: `${president.name} ${president.lastName}`, inicio_periodo: president.startPeriodDate, fin_periodo: president.endPeriodDate, partido_politico: president.politicalParty, descripcion: president.description, imagen: president.image, }; return { content: [ { type: "text", text: JSON.stringify(resultado, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error al obtener presidente: ${error instanceof Error ? error.message : "Error desconocido"}`, }, ], }; } } ); // 10. Obtener aeropuertos server.registerTool( "get_airports", { title: "Obtener Aeropuertos de Colombia", description: `Obtiene la lista de aeropuertos de Colombia. Puede filtrar por departamento. Args: - department_id (number, opcional): ID del departamento para filtrar Returns: Lista de aeropuertos con nombre, ciudad, tipo y códigos IATA/OACI. Ejemplo de uso: - "¿Cuáles son los aeropuertos de Colombia?" - "Aeropuertos en Antioquia"`, inputSchema: { department_id: z.number().int().optional().describe("ID del departamento para filtrar"), }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async ({ department_id }) => { try { let airports: any[]; if (department_id) { airports = await apiRequest<any[]>(`/Department/${department_id}/airports`); } else { airports = await apiRequest<any[]>("/Airport"); } const resultado = { total: airports.length, aeropuertos: airports.map(a => ({ id: a.id, nombre: a.name, ciudad: a.city?.name || "N/A", departamento: a.department?.name || "N/A", tipo: a.type, codigo_iata: a.iataCode, codigo_oaci: a.oaciCode, latitud: a.latitude, longitud: a.longitude, })), }; return { content: [ { type: "text", text: JSON.stringify(resultado, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error al obtener aeropuertos: ${error instanceof Error ? error.message : "Error desconocido"}`, }, ], }; } } ); // 11. Obtener emisoras de radio server.registerTool( "get_radios", { title: "Obtener Emisoras de Radio", description: `Obtiene la lista de emisoras de radio de Colombia. Puede filtrar por ciudad. Args: - city_id (number, opcional): ID de la ciudad para filtrar Returns: Lista de emisoras con nombre, frecuencia, ciudad y URL de streaming. Ejemplo de uso: - "¿Qué emisoras de radio hay en Colombia?" - "Emisoras de radio en Bogotá"`, inputSchema: { city_id: z.number().int().optional().describe("ID de la ciudad para filtrar"), }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async ({ city_id }) => { try { let radios: any[]; if (city_id) { radios = await apiRequest<any[]>(`/City/${city_id}/radios`); } else { radios = await apiRequest<any[]>("/Radio"); } const resultado = { total: radios.length, emisoras: radios.slice(0, 50).map(r => ({ id: r.id, nombre: r.name, frecuencia: r.frequency, ciudad: r.city?.name || "N/A", url_streaming: r.streamingUrl, })), }; return { content: [ { type: "text", text: JSON.stringify(resultado, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error al obtener emisoras: ${error instanceof Error ? error.message : "Error desconocido"}`, }, ], }; } } ); // 12. Obtener resguardos indígenas server.registerTool( "get_indigenous_reservations", { title: "Obtener Resguardos Indígenas", description: `Obtiene la lista de resguardos indígenas de Colombia. Puede filtrar por departamento. Args: - department_id (number, opcional): ID del departamento para filtrar Returns: Lista de resguardos indígenas con nombre, comunidad y departamento. Ejemplo de uso: - "¿Cuáles son los resguardos indígenas de Colombia?" - "Resguardos indígenas en el Cauca"`, inputSchema: { department_id: z.number().int().optional().describe("ID del departamento para filtrar"), }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async ({ department_id }) => { try { let reservations: any[]; if (department_id) { reservations = await apiRequest<any[]>(`/Department/${department_id}/indigenousreservations`); } else { reservations = await apiRequest<any[]>("/IndigenousReservation"); } const resultado = { total: reservations.length, resguardos: reservations.slice(0, 50).map(r => ({ id: r.id, nombre: r.name, codigo: r.code, comunidad_nativa: r.nativeCommunity, departamento_id: r.departmentId, ciudad_id: r.cityId, })), }; return { content: [ { type: "text", text: JSON.stringify(resultado, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error al obtener resguardos indígenas: ${error instanceof Error ? error.message : "Error desconocido"}`, }, ], }; } } ); // 13. Obtener áreas naturales server.registerTool( "get_natural_areas", { title: "Obtener Áreas Naturales Protegidas", description: `Obtiene la lista de áreas naturales protegidas de Colombia. Puede filtrar por departamento. Args: - department_id (number, opcional): ID del departamento para filtrar Returns: Lista de áreas naturales con nombre, categoría y departamento. Ejemplo de uso: - "¿Cuáles son los parques naturales de Colombia?" - "Áreas naturales en el Amazonas"`, inputSchema: { department_id: z.number().int().optional().describe("ID del departamento para filtrar"), }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async ({ department_id }) => { try { let areas: any[]; if (department_id) { areas = await apiRequest<any[]>(`/Department/${department_id}/naturalareas`); } else { areas = await apiRequest<any[]>("/NaturalArea"); } const resultado = { total: areas.length, areas_naturales: areas.map(a => ({ id: a.id, nombre: a.name, categoria: a.categoryNaturalArea?.name || "N/A", departamento_id: a.departmentId, area_hectareas: a.areaHa, })), }; return { content: [ { type: "text", text: JSON.stringify(resultado, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error al obtener áreas naturales: ${error instanceof Error ? error.message : "Error desconocido"}`, }, ], }; } } ); // 14. Obtener mapas de departamentos server.registerTool( "get_maps", { title: "Obtener Mapas", description: `Obtiene mapas de Colombia o de un departamento específico. Args: - department_id (number, opcional): ID del departamento para obtener su mapa Returns: URLs de mapas del departamento o país. Ejemplo de uso: - "Dame el mapa de Antioquia" - "Quiero ver mapas de Colombia"`, inputSchema: { department_id: z.number().int().optional().describe("ID del departamento"), }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async ({ department_id }) => { try { let maps: any[]; if (department_id) { maps = await apiRequest<any[]>(`/Department/${department_id}/maps`); } else { maps = await apiRequest<any[]>("/Map"); } const resultado = { total: maps.length, mapas: maps.map(m => ({ id: m.id, nombre: m.name, descripcion: m.description, url: m.url, departamento_id: m.departmentId, })), }; return { content: [ { type: "text", text: JSON.stringify(resultado, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error al obtener mapas: ${error instanceof Error ? error.message : "Error desconocido"}`, }, ], }; } } ); // 15. Buscar información general server.registerTool( "search_colombia", { title: "Buscar en Colombia", description: `Herramienta de búsqueda general que intenta encontrar información sobre departamentos, ciudades o lugares turísticos. Args: - query (string): Término de búsqueda (nombre de departamento, ciudad o lugar) Returns: Resultados de búsqueda con la información encontrada. Ejemplo de uso: - "Busca Medellín" - "Información sobre el Parque Tayrona"`, inputSchema: { query: z.string().min(2).describe("Término de búsqueda"), }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async ({ query }) => { try { const resultados: { tipo: string; datos: unknown; }[] = []; // Buscar en departamentos try { const dept = await apiRequest<Department>(`/Department/name/${encodeURIComponent(query)}`); if (dept) { resultados.push({ tipo: "departamento", datos: { id: dept.id, nombre: dept.name, descripcion: dept.description, capital: dept.cityCapital?.name, poblacion: dept.population, }, }); } } catch { // No encontrado como departamento } // Buscar en atracciones turísticas try { const attractions = await apiRequest<TouristAttraction[]>(`/TouristAttraction/search/${encodeURIComponent(query)}`); if (attractions && attractions.length > 0) { resultados.push({ tipo: "atracciones_turisticas", datos: attractions.slice(0, 5).map(a => ({ id: a.id, nombre: a.name, descripcion: a.description?.substring(0, 200) + "...", })), }); } } catch { // No encontrado } if (resultados.length === 0) { return { content: [ { type: "text", text: `No se encontraron resultados para "${query}". Intenta con otro término.`, }, ], }; } return { content: [ { type: "text", text: JSON.stringify({ query, resultados }, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error en la búsqueda: ${error instanceof Error ? error.message : "Error desconocido"}`, }, ], }; } } ); // ============================================ // INICIAR SERVIDOR // ============================================ async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error("Colombia MCP Server iniciado correctamente"); } main().catch((error) => { console.error("Error al iniciar el servidor:", error); process.exit(1); });

Implementation Reference

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/crexative/colombia-mcp-server'

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