Skip to main content
Glama
Licinexus

licinexus-mcp

Official
by Licinexus

get_licitacao

Retrieve complete details of a Brazilian procurement bid (licitação) from PNCP using the control number or agency CNPJ, year, and sequential number.

Instructions

Get the full details of a single licitação (procurement bid) on PNCP. Provide either numeroControlePNCP (the full PNCP control number string) or all three of orgaoCnpj, ano, sequencial.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
numeroControlePNCPNoPNCP control number, format like 00000000000000-1-000001/2024
orgaoCnpjNoProcuring agency CNPJ (14 digits)
anoNoYear of the bid (e.g. 2024)
sequencialNoSequential number of the bid

Implementation Reference

  • The main handler function for the get_licitacao tool. Parses arguments using PncpIdInputSchema, resolves the PNCP ID (via numeroControlePNCP or orgaoCnpj/ano/sequencial), calls getContratacao to fetch the data from the PNCP API, and returns the result as JSON.
      async handler(rawArgs) {
        const parse = ArgsSchema.safeParse(rawArgs ?? {});
        if (!parse.success) {
          return errorResult(`Invalid arguments: ${parse.error.message}`);
        }
        try {
          const { orgaoCnpj, ano, sequencial } = resolvePncpId(parse.data);
          const data = await getContratacao(orgaoCnpj, ano, sequencial);
          return jsonResult(data);
        } catch (err) {
          const msg = err instanceof PncpError ? err.message : String(err);
          return errorResult(`Failed to get licitação: ${msg}`);
        }
      },
    };
  • PncpIdInputSchema: Zod schema defining the input for get_licitacao. Accepts either numeroControlePNCP (string) or all three of orgaoCnpj (string), ano (integer), and sequencial (integer). Validates that one group or the other is provided.
    export const PncpIdInputSchema = z
      .object({
        numeroControlePNCP: z.string().optional(),
        orgaoCnpj: z.string().optional(),
        ano: z.number().int().optional(),
        sequencial: z.number().int().optional(),
      })
      .refine(
        (v) =>
          Boolean(v.numeroControlePNCP) ||
          (Boolean(v.orgaoCnpj) && Boolean(v.ano) && Boolean(v.sequencial)),
        {
          message: 'Provide either numeroControlePNCP, or all three of orgaoCnpj/ano/sequencial.',
        },
      );
  • ContratacaoSchema: Zod schema defining the response shape for a licitação (procurement bid). Includes fields like numeroControlePNCP, anoCompra, sequencialCompra, orgaoEntidade, modalidadeNome, objetoCompra, valorTotalEstimado, valorTotalHomologado, dates, etc.
    export const ContratacaoSchema = z
      .object({
        numeroControlePNCP: z.string(),
        anoCompra: z.number(),
        sequencialCompra: z.number(),
        numeroCompra: z.string().nullable().optional(),
        processo: z.string().nullable().optional(),
        orgaoEntidade: orgaoEntidadeSchema.nullable().optional(),
        unidadeOrgao: unidadeOrgaoSchema.nullable().optional(),
        modalidadeId: z.number().nullable().optional(),
        modalidadeNome: z.string().nullable().optional(),
        modoDisputaId: z.number().nullable().optional(),
        modoDisputaNome: z.string().nullable().optional(),
        srp: z.boolean().nullable().optional(),
        objetoCompra: z.string().nullable().optional(),
        informacaoComplementar: z.string().nullable().optional(),
        valorTotalEstimado: z.number().nullable().optional(),
        valorTotalHomologado: z.number().nullable().optional(),
        situacaoCompraId: z.number().nullable().optional(),
        situacaoCompraNome: z.string().nullable().optional(),
        dataPublicacaoPncp: z.string().nullable().optional(),
        dataAberturaProposta: z.string().nullable().optional(),
        dataEncerramentoProposta: z.string().nullable().optional(),
        dataInclusao: z.string().nullable().optional(),
        dataAtualizacao: z.string().nullable().optional(),
        linkSistemaOrigem: z.string().nullable().optional(),
        linkProcessoEletronico: z.string().nullable().optional(),
        amparoLegal: amparoLegalSchema.nullable().optional(),
        tipoInstrumentoConvocatorioCodigo: z.number().nullable().optional(),
        tipoInstrumentoConvocatorioNome: z.string().nullable().optional(),
      })
      .passthrough();
  • Registration of getLicitacao in the allTools array (line 24) and construction of the toolMap (line 49) which maps tool name 'get_licitacao' to its ToolDef.
    import { getLicitacao } from './get_licitacao.js';
    import { listLicitacaoItens } from './list_licitacao_itens.js';
    import { listLicitacaoResultados } from './list_licitacao_resultados.js';
    import { listLicitacaoArquivos } from './list_licitacao_arquivos.js';
    import { searchContratos } from './search_contratos.js';
    import { getContratoTool } from './get_contrato.js';
    import { listContratoTermosTool } from './list_contrato_termos.js';
    import { listContratoInstrumentosTool } from './list_contrato_instrumentos.js';
    import { searchAtasRp } from './search_atas_rp.js';
    import { getAtaRp } from './get_ata_rp.js';
    import { getOrgaoTool } from './get_orgao.js';
    import { getFornecedorContratos } from './get_fornecedor_contratos.js';
    import { searchPca } from './search_pca.js';
    import { listPcaItensTool } from './list_pca_itens.js';
    import { getCnpjDataTool } from './get_cnpj_data.js';
    import { aggregateLicitacoes } from './aggregate_licitacoes.js';
    import { comparePeriodos } from './compare_periodos.js';
    
    export const allTools: ToolDef[] = [
      // Compras / Licitações
      searchLicitacoes,
      getLicitacao,
      listLicitacaoItens,
      listLicitacaoResultados,
      listLicitacaoArquivos,
      // Contratos
      searchContratos,
      getContratoTool,
      listContratoTermosTool,
      listContratoInstrumentosTool,
      // Atas RP
      searchAtasRp,
      getAtaRp,
      // Órgãos / Fornecedores
      getOrgaoTool,
      getFornecedorContratos,
      // PCA
      searchPca,
      listPcaItensTool,
      // CNPJ enrichment
      getCnpjDataTool,
      // Análise agregada (v0.2.0)
      aggregateLicitacoes,
      comparePeriodos,
    ];
    
    export const toolMap = new Map<string, ToolDef>(allTools.map((t) => [t.definition.name, t]));
  • getContratacao: The downstream API call that fetches a single licitação from the PNCP consulta API endpoint. Includes caching (TTL_30_MIN) and error handling via PncpError.
    export async function getContratacao(
      orgaoCnpj: string,
      ano: number,
      sequencial: number,
    ): Promise<Contratacao> {
      const cacheKey = `get:contratacao:${orgaoCnpj}:${ano}:${sequencial}`;
      const cached = cache.get<Contratacao>(cacheKey);
      if (cached) return cached;
    
      try {
        // PNCP moved this detail endpoint from /api/pncp/v1 to /api/consulta/v1
        const { data } = await withRetry(() =>
          consultaClient.get(`/orgaos/${orgaoCnpj}/compras/${ano}/${sequencial}`),
        );
        const parsed = ContratacaoSchema.parse(data);
        cache.set(cacheKey, parsed, TTL_30_MIN);
        return parsed;
      } catch (err) {
        if (err instanceof AxiosError) {
          throw new PncpError(describeAxiosError(err), err);
        }
        throw err;
      }
    }
Behavior2/5

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

No annotations are present, so the description carries full burden. It only states the retrieval action without disclosing read-only status, error handling, rate limits, or authentication needs. The description adds minimal behavioral context beyond the tool name.

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?

Two sentences, efficient and front-loaded with the core purpose. Every word serves a purpose; no redundancy.

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, the description could hint at the returned data structure. It does not. While sibling tools exist, no comparative guidance is provided. The description is adequate but not comprehensive for a simple getter.

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

Parameters4/5

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

Schema coverage is 100% with descriptions for all parameters. The description adds valuable grouping semantics, clarifying that the parameters form two exclusive sets. This goes beyond the individual schema descriptions.

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?

The description clearly states the verb 'Get' and the resource 'full details of a single licitação (procurement bid) on PNCP'. It specifies two distinct input options, distinguishing it from sibling tools like search_licitacoes or list_licitacao_itens.

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

Usage Guidelines4/5

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

The description explicitly provides two valid input combinations: either numeroControlePNCP or the trio of orgaoCnpj, ano, sequencial. However, it does not mention when not to use this tool or compare it to similar siblings like get_ata_rp.

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/Licinexus/licinexus-mcp'

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