senado_listar_votacoes
Retrieve Brazilian Senate plenary votes by year, with optional filtering by month or date range for targeted analysis.
Instructions
Lista votações do plenário do Senado por ano, podendo filtrar por mês ou período específico.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| ano | Yes | Ano das votações (obrigatório) | |
| mes | No | Mês (1-12) | |
| dataInicio | No | Data início (YYYYMMDD) | |
| dataFim | No | Data fim (YYYYMMDD) |
Implementation Reference
- src/tools/votacoes.ts:92-148 (handler)The async handler function for the 'senado_listar_votacoes' tool. It parses input (ano, mes, dataInicio, dataFim), builds the API endpoint URL, fetches voting data from the Senado API, extracts and formats voting summaries, and returns the response.
async (params) => { try { const input = ListarVotacoesInput.parse(params); logger.info({ input }, 'Listing votacoes'); let endpoint = ENDPOINTS.VOTACOES_ANO(input.ano); // Add query params if provided const queryParams: string[] = []; if (input.mes) queryParams.push(`mes=${input.mes}`); if (input.dataInicio) queryParams.push(`dataInicio=${input.dataInicio}`); if (input.dataFim) queryParams.push(`dataFim=${input.dataFim}`); if (queryParams.length > 0) { endpoint += '?' + queryParams.join('&'); } const response = await apiRequest<any>(endpoint); let votacoes: any[] = []; if (response.ListaVotacoes?.Votacoes?.Votacao) { votacoes = response.ListaVotacoes.Votacoes.Votacao; } else if (response.VotacoesPlenario?.Votacoes?.Votacao) { votacoes = response.VotacoesPlenario.Votacoes.Votacao; } if (!Array.isArray(votacoes)) { votacoes = votacoes ? [votacoes] : []; } const votacoesFormatadas = votacoes.map(parseVotacaoResumo); const result = createSuccessResponse( { ano: input.ano, count: votacoesFormatadas.length, votacoes: votacoesFormatadas }, endpoint ); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } catch (error) { logger.error({ error }, 'Error listing votacoes'); const errorResult = createErrorResponse( 'ERRO_LISTAR_VOTACOES', error instanceof Error ? error.message : 'Erro ao listar votações', 'Verifique se o ano está correto' ); return { content: [{ type: 'text', text: JSON.stringify(errorResult, null, 2) }] }; } } ); - src/tools/votacoes.ts:82-148 (registration)The registration of the 'senado_listar_votacoes' tool on the McpServer via server.tool(), including its name, description, Zod-based input schema, and the handler function.
// senado_listar_votacoes server.tool( 'senado_listar_votacoes', 'Lista votações do plenário do Senado por ano, podendo filtrar por mês ou período específico.', { ano: z.number().int().min(1900).max(2100).describe('Ano das votações (obrigatório)'), mes: z.number().int().min(1).max(12).optional().describe('Mês (1-12)'), dataInicio: z.string().regex(/^\d{8}$/).optional().describe('Data início (YYYYMMDD)'), dataFim: z.string().regex(/^\d{8}$/).optional().describe('Data fim (YYYYMMDD)') }, async (params) => { try { const input = ListarVotacoesInput.parse(params); logger.info({ input }, 'Listing votacoes'); let endpoint = ENDPOINTS.VOTACOES_ANO(input.ano); // Add query params if provided const queryParams: string[] = []; if (input.mes) queryParams.push(`mes=${input.mes}`); if (input.dataInicio) queryParams.push(`dataInicio=${input.dataInicio}`); if (input.dataFim) queryParams.push(`dataFim=${input.dataFim}`); if (queryParams.length > 0) { endpoint += '?' + queryParams.join('&'); } const response = await apiRequest<any>(endpoint); let votacoes: any[] = []; if (response.ListaVotacoes?.Votacoes?.Votacao) { votacoes = response.ListaVotacoes.Votacoes.Votacao; } else if (response.VotacoesPlenario?.Votacoes?.Votacao) { votacoes = response.VotacoesPlenario.Votacoes.Votacao; } if (!Array.isArray(votacoes)) { votacoes = votacoes ? [votacoes] : []; } const votacoesFormatadas = votacoes.map(parseVotacaoResumo); const result = createSuccessResponse( { ano: input.ano, count: votacoesFormatadas.length, votacoes: votacoesFormatadas }, endpoint ); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } catch (error) { logger.error({ error }, 'Error listing votacoes'); const errorResult = createErrorResponse( 'ERRO_LISTAR_VOTACOES', error instanceof Error ? error.message : 'Erro ao listar votações', 'Verifique se o ano está correto' ); return { content: [{ type: 'text', text: JSON.stringify(errorResult, null, 2) }] }; } } ); - src/schemas/votacao.ts:4-27 (schema)The Zod input validation schema for ListarVotacoesInput, defining the required 'ano' field and optional 'mes', 'dataInicio', 'dataFim' fields with validation rules.
export const ListarVotacoesInput = z.object({ ano: z.number() .int() .min(1900) .max(2100) .describe('Ano das votações (obrigatório)'), mes: z.number() .int() .min(1) .max(12) .optional() .describe('Mês (1-12)'), dataInicio: z.string() .regex(/^\d{8}$/, 'Formato deve ser YYYYMMDD') .optional() .describe('Data início (YYYYMMDD)'), dataFim: z.string() .regex(/^\d{8}$/, 'Formato deve ser YYYYMMDD') .optional() .describe('Data fim (YYYYMMDD)') }); - src/tools/votacoes.ts:16-32 (helper)Helper function that parses raw API response data into a formatted VotacaoResumoType object, extracting fields like codigo, data, hora, materia, descricao, resultado, and vote totals.
function parseVotacaoResumo(votacao: any): VotacaoResumoType { const sessao = votacao.SessaoPlenaria || votacao; const materia = votacao.IdentificacaoMateria || {}; return { codigo: parseInt(votacao.CodigoSessaoVotacao || votacao.CodigoVotacao || sessao.CodigoSessao || '0'), data: sessao.DataSessao || votacao.DataSessao || votacao.Data || '', hora: sessao.HoraInicioSessao || votacao.Hora || null, materia: materia.DescricaoIdentificacaoMateria || `${materia.SiglaSubtipoMateria || ''} ${materia.NumeroMateria || ''}/${materia.AnoMateria || ''}`.trim() || null, descricao: votacao.DescricaoVotacao || sessao.DescricaoTipoSessao || null, resultado: votacao.DescricaoResultado || votacao.Resultado || null, totalSim: votacao.TotalVotosSim ? parseInt(votacao.TotalVotosSim) : null, totalNao: votacao.TotalVotosNao ? parseInt(votacao.TotalVotosNao) : null, totalAbstencao: votacao.TotalVotosAbstencao ? parseInt(votacao.TotalVotosAbstencao) : null }; } - src/api/endpoints.ts:3-38 (helper)The endpoint definition VOTACOES_ANO that generates the URL path for listing votacoes by year, used by the tool's handler.
export const ENDPOINTS = { // Senadores SENADORES_ATUAIS: '/senador/lista/atual', SENADORES_LEGISLATURA: (leg: number) => `/senador/lista/legislatura/${leg}`, SENADOR: (codigo: number) => `/senador/${codigo}`, SENADOR_VOTACOES: (codigo: number) => `/senador/${codigo}/votacoes`, SENADOR_MANDATOS: (codigo: number) => `/senador/${codigo}/mandatos`, SENADOR_CARGOS: (codigo: number) => `/senador/${codigo}/cargos`, SENADOR_COMISSOES: (codigo: number) => `/senador/${codigo}/comissoes`, // Matérias MATERIAS_PESQUISA: '/materia/pesquisa/lista', MATERIA: (codigo: number) => `/materia/${codigo}`, MATERIA_TEXTOS: (codigo: number) => `/materia/${codigo}/textos`, MATERIA_VOTACOES: (codigo: number) => `/materia/${codigo}/votacoes`, MATERIAS_TRAMITANDO: '/materia/tramitando', // Votações VOTACOES_ANO: (ano: number) => `/plenario/lista/votacao/${ano}`, VOTACAO: (codigo: number) => `/plenario/votacao/${codigo}`, VOTACAO_VOTOS: (codigo: number) => `/plenario/votacao/${codigo}/votos`, // Comissões COMISSOES_LISTA: '/comissao/lista', COMISSAO: (sigla: string) => `/comissao/${sigla}`, COMISSAO_COMPOSICAO: (sigla: string) => `/comissao/${sigla}/composicao`, // Agenda AGENDA: (data: string) => `/agenda/${data}`, SESSOES_ANO: (ano: number) => `/plenario/lista/sessoes/${ano}`, // Auxiliares LEGISLATURA_ATUAL: '/legislatura/atual', MATERIA_SIGLAS: '/materia/siglas', PARTIDOS_LISTA: '/partido/lista', } as const;