Skip to main content
Glama

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

TableJSON Schema
NameRequiredDescriptionDefault
anoYesAno das votações (obrigatório)
mesNoMês (1-12)
dataInicioNoData início (YYYYMMDD)
dataFimNoData fim (YYYYMMDD)

Implementation Reference

  • 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) }]
          };
        }
      }
    );
  • 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) }]
          };
        }
      }
    );
  • 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)')
    });
  • 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
      };
    }
  • 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;
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. It implies a read-only listing operation but does not disclose pagination, authentication needs, or edge cases like empty results. Adequate but not thorough.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence that is concise and to the point. No unnecessary words; every part adds meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, description could explain return format or potential errors. It covers the core function and filters but lacks completeness for a tool with 4 parameters and no annotations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 100% coverage with descriptions for all 4 parameters. The description adds minimal value by summarizing the filter options (ano, mes, período), but does not provide additional semantics beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states verb 'Lista', resource 'votações do plenário do Senado', and scope 'por ano' with optional filters. It distinguishes from sibling tools like 'senado_votacoes_recentes' by specifying yearly listing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives like 'senado_votacoes_recentes' or 'senado_votacoes_senador'. The description only explains what it does, not when it is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/SidneyBissoli/senado-br-mcp'

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