Skip to main content
Glama

Star Wars MCP Server

by glaucia86
index.ts8.88 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"; import axios, { AxiosError } from "axios"; import { People, Planets, Films, SearchResponse } from "./types.js"; const SWAPI_BASE_URL = "https://swapi.dev/api"; class SwapiMcpServer { private server: McpServer; private axiosInstance; constructor() { this.server = new McpServer({ name: "swapi-mcp-server", version: "1.0.0", }); this.axiosInstance = axios.create({ baseURL: SWAPI_BASE_URL, timeout: 10000, }); this.setupTools(); this.setupResources(); } private setupTools(): void { this.server.registerTool( "search_characters", { title: "Buscar Personagens", description: "Busca personagens do Star Wars por nome", inputSchema: { search: z.string().describe("Nome do personagem para buscar"), }, }, async ({ search }) => { try { const response = await this.axiosInstance.get<SearchResponse<People>>( "/people/", { params: { search }, } ); if (response.data.results.length === 0) { return { content: [ { type: "text" as const, text: `Nenhum personagem encontrado com o nome "${search}".`, }, ], }; } const charactersInfo = response.data.results .map((char) => { return `Nome: ${char.name} Altura: ${char.height}cm Massa: ${char.mass}kg Cor do Cabelo: ${char.hair_color} Cor dos Olhos: ${char.eye_color} Ano de Nascimento: ${char.birth_year} Gênero: ${char.gender} `; }) .join("\n---\n\n"); return { content: [ { type: "text" as const, text: `Encontrados ${response.data.results.length} personagem(ns):\n\n${charactersInfo}`, }, ], }; } catch (error) { return this.handleError(error, "buscar personagens"); } } ); this.server.registerTool( "search_planets", { title: "Buscar Planetas", description: "Busca planetas do Star Wars por nome", inputSchema: { search: z.string().describe("Nome do planeta para buscar"), }, }, async ({ search }) => { try { const response = await this.axiosInstance.get<SearchResponse<Planets>>( "/planets/", { params: { search }, } ); if (response.data.results.length === 0) { return { content: [ { type: "text" as const, text: `Nenhum planeta encontrado com o nome "${search}".`, }, ], }; } const planetsInfo = response.data.results .map((planet) => { return `Nome: ${planet.name} Clima: ${planet.climate} Terreno: ${planet.terrain} População: ${planet.population} Diâmetro: ${planet.diameter}km Período de Rotação: ${planet.rotation_period}h Período Orbital: ${planet.orbital_period} dias `; }) .join("\n---\n\n"); return { content: [ { type: "text" as const, text: `Encontrados ${response.data.results.length} planeta(s):\n\n${planetsInfo}`, }, ], }; } catch (error) { return this.handleError(error, "buscar planetas"); } } ); this.server.registerTool( "search_films", { title: "Buscar Filmes", description: "Busca filmes do Star Wars por título", inputSchema: { search: z.string().describe("Título do filme para buscar"), }, }, async ({ search }) => { try { const response = await this.axiosInstance.get<SearchResponse<Films>>( "/films/", { params: { search }, } ); if (response.data.results.length === 0) { return { content: [ { type: "text" as const, text: `Nenhum filme encontrado com o título "${search}".`, }, ], }; } const filmsInfo = response.data.results .map((film) => { return `Título: ${film.title} Episódio: ${film.episode_id} Diretor: ${film.director} Produtor: ${film.producer} Data de Lançamento: ${film.release_date} Abertura: ${film.opening_crawl}`; }) .join("\n---\n\n"); return { content: [ { type: "text" as const, text: `Encontrados ${response.data.results.length} filme(s):\n\n${filmsInfo}`, }, ], }; } catch (error) { return this.handleError(error, "buscar filmes"); } } ); this.server.registerTool( "get_character_by_id", { title: "Obter Personagem por ID", description: "Obtém informações detalhadas de um personagem pelo ID", inputSchema: { id: z.number().describe("ID do personagem"), }, }, async ({ id }) => { try { const response = await this.axiosInstance.get<People>( `/people/${id}/` ); const char = response.data; const characterInfo = `Nome: ${char.name} Altura: ${char.height}cm Massa: ${char.mass}kg Cor do Cabelo: ${char.hair_color} Cor dos Olhos: ${char.eye_color} Ano de Nascimento: ${char.birth_year} Gênero: ${char.gender} URL do Mundo Natal: ${char.homeworld} Número de Filmes: ${char.films.length}`; return { content: [ { type: "text" as const, text: characterInfo, }, ], }; } catch (error) { return this.handleError(error, `obter personagem com ID ${id}`); } } ); } private setupResources(): void { this.server.registerResource( "all_films", "swapi://films/all", { name: "Todos os Filmes", description: "Lista todos os filmes da saga Star Wars", mimeType: "text/plain", }, async () => { try { const response = await this.axiosInstance.get<SearchResponse<Films>>( "/films/" ); const filmsInfo = response.data.results .sort((a, b) => a.episode_id - b.episode_id) .map((film) => { return `Episódio ${film.episode_id}: ${film.title} Diretor: ${film.director} Lançamento: ${film.release_date}`; }) .join("\n\n"); return { contents: [ { uri: "swapi://films/all", mimeType: "text/plain", text: `Filmes da Saga Star Wars:\n\n${filmsInfo}`, }, ], }; } catch (error) { throw new Error(`Erro ao buscar filmes: ${error}`); } } ); } private handleError(error: unknown, operation: string) { if (axios.isAxiosError(error)) { const axiosError = error as AxiosError; return { content: [ { type: "text" as const, text: `Erro ao ${operation}: ${ axiosError.response?.data || axiosError.message || "Erro desconhecido" }`, }, ], isError: true, }; } return { content: [ { type: "text" as const, text: `Erro inesperado ao ${operation}: ${error}`, }, ], isError: true, }; } async run(): Promise<void> { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error("SWAPI MCP Server rodando em stdio"); } } const server = new SwapiMcpServer(); server.run().catch((error) => { console.error("Erro fatal ao iniciar o servidor:", error); process.exit(1); });

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/glaucia86/swapi-mcp-server-app'

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