bcb-br-mcp 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
package/dist/tools.js CHANGED
@@ -11,15 +11,27 @@ export const CONFIG = {
11
11
  TIMEOUT_MS: 30000,
12
12
  MAX_RETRIES: 3,
13
13
  RETRY_DELAY_MS: 1000,
14
- USER_AGENT: "bcb-br-mcp/1.2.0"
14
+ USER_AGENT: "bcb-br-mcp/1.3.0"
15
15
  };
16
16
  // Worker uses shorter timeout (Cloudflare has its own limits)
17
17
  export const WORKER_CONFIG = {
18
18
  TIMEOUT_MS: 10000,
19
19
  MAX_RETRIES: 2,
20
20
  RETRY_DELAY_MS: 1000,
21
- USER_AGENT: "bcb-br-mcp/1.2.0"
21
+ USER_AGENT: "bcb-br-mcp/1.3.0"
22
22
  };
23
+ // ==================== OUTPUT HELPER ====================
24
+ /**
25
+ * Builds a ToolResult that satisfies an MCP tool's outputSchema:
26
+ * the same payload is exposed as machine-readable structuredContent and,
27
+ * for backward compatibility, serialized into a TextContent block.
28
+ */
29
+ function structuredResult(payload) {
30
+ return {
31
+ content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
32
+ structuredContent: payload
33
+ };
34
+ }
23
35
  // ==================== SERIES CATALOG ====================
24
36
  export const SERIES_POPULARES = [
25
37
  // ==================== JUROS E TAXAS ====================
@@ -283,25 +295,28 @@ export async function handleSerieValores(args, timeoutMs, maxRetries) {
283
295
  if (args.dataFinal)
284
296
  url += `&dataFinal=${formatDateForApi(args.dataFinal)}`;
285
297
  const data = await fetchBcbApi(url, timeoutMs, maxRetries);
298
+ const serieInfo = SERIES_POPULARES.find(s => s.codigo === args.codigo);
299
+ const serie = {
300
+ codigo: args.codigo,
301
+ nome: serieInfo?.nome || `Série ${args.codigo}`,
302
+ categoria: serieInfo?.categoria || "Desconhecida",
303
+ periodicidade: serieInfo?.periodicidade || "Desconhecida"
304
+ };
286
305
  if (!Array.isArray(data) || data.length === 0) {
287
- return {
288
- content: [{ type: "text", text: `Nenhum dado encontrado para a série ${args.codigo} no período solicitado.` }]
289
- };
306
+ return structuredResult({
307
+ serie,
308
+ totalRegistros: 0,
309
+ dados: [],
310
+ observacao: `Nenhum dado encontrado para a série ${args.codigo} no período solicitado.`
311
+ });
290
312
  }
291
- const serieInfo = SERIES_POPULARES.find(s => s.codigo === args.codigo);
292
- const result = {
293
- serie: {
294
- codigo: args.codigo,
295
- nome: serieInfo?.nome || `Série ${args.codigo}`,
296
- categoria: serieInfo?.categoria || "Desconhecida",
297
- periodicidade: serieInfo?.periodicidade || "Desconhecida"
298
- },
313
+ return structuredResult({
314
+ serie,
299
315
  totalRegistros: data.length,
300
316
  periodoInicial: data[0].data,
301
317
  periodoFinal: data[data.length - 1].data,
302
318
  dados: data.map(d => ({ data: d.data, valor: parseFloat(d.valor) }))
303
- };
304
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
319
+ });
305
320
  }
306
321
  catch (error) {
307
322
  return {
@@ -314,23 +329,26 @@ export async function handleSerieUltimos(args, timeoutMs, maxRetries) {
314
329
  try {
315
330
  const url = `${BCB_API_BASE}.${args.codigo}/dados/ultimos/${args.quantidade}?formato=json`;
316
331
  const data = await fetchBcbApi(url, timeoutMs, maxRetries);
332
+ const serieInfo = SERIES_POPULARES.find(s => s.codigo === args.codigo);
333
+ const serie = {
334
+ codigo: args.codigo,
335
+ nome: serieInfo?.nome || `Série ${args.codigo}`,
336
+ categoria: serieInfo?.categoria || "Desconhecida",
337
+ periodicidade: serieInfo?.periodicidade || "Desconhecida"
338
+ };
317
339
  if (!Array.isArray(data) || data.length === 0) {
318
- return {
319
- content: [{ type: "text", text: `Nenhum dado encontrado para a série ${args.codigo}.` }]
320
- };
340
+ return structuredResult({
341
+ serie,
342
+ totalRegistros: 0,
343
+ dados: [],
344
+ observacao: `Nenhum dado encontrado para a série ${args.codigo}.`
345
+ });
321
346
  }
322
- const serieInfo = SERIES_POPULARES.find(s => s.codigo === args.codigo);
323
- const result = {
324
- serie: {
325
- codigo: args.codigo,
326
- nome: serieInfo?.nome || `Série ${args.codigo}`,
327
- categoria: serieInfo?.categoria || "Desconhecida",
328
- periodicidade: serieInfo?.periodicidade || "Desconhecida"
329
- },
347
+ return structuredResult({
348
+ serie,
330
349
  totalRegistros: data.length,
331
350
  dados: data.map(d => ({ data: d.data, valor: parseFloat(d.valor) }))
332
- };
333
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
351
+ });
334
352
  }
335
353
  catch (error) {
336
354
  return {
@@ -345,7 +363,7 @@ export async function handleSerieMetadados(args, timeoutMs, maxRetries) {
345
363
  try {
346
364
  const metadata = await fetchBcbApi(metadataUrl, timeoutMs, maxRetries);
347
365
  const serieInfo = SERIES_POPULARES.find(s => s.codigo === args.codigo);
348
- const result = {
366
+ return structuredResult({
349
367
  codigo: metadata.codigo || args.codigo,
350
368
  nome: metadata.nome || serieInfo?.nome || `Série ${args.codigo}`,
351
369
  unidade: metadata.unidade || "Não informada",
@@ -355,13 +373,12 @@ export async function handleSerieMetadados(args, timeoutMs, maxRetries) {
355
373
  especial: metadata.especial || false,
356
374
  urlConsulta: `${BCB_API_BASE}.${args.codigo}/dados?formato=json`,
357
375
  urlUltimos10: `${BCB_API_BASE}.${args.codigo}/dados/ultimos/10?formato=json`
358
- };
359
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
376
+ });
360
377
  }
361
378
  catch {
362
379
  const serieInfo = SERIES_POPULARES.find(s => s.codigo === args.codigo);
363
380
  if (serieInfo) {
364
- const result = {
381
+ return structuredResult({
365
382
  codigo: args.codigo,
366
383
  nome: serieInfo.nome,
367
384
  periodicidade: serieInfo.periodicidade,
@@ -370,21 +387,19 @@ export async function handleSerieMetadados(args, timeoutMs, maxRetries) {
370
387
  urlConsulta: `${BCB_API_BASE}.${args.codigo}/dados?formato=json`,
371
388
  urlUltimos10: `${BCB_API_BASE}.${args.codigo}/dados/ultimos/10?formato=json`,
372
389
  observacao: "Metadados obtidos do catálogo interno"
373
- };
374
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
390
+ });
375
391
  }
376
392
  const url = `${BCB_API_BASE}.${args.codigo}/dados/ultimos/1?formato=json`;
377
393
  const data = await fetchBcbApi(url, timeoutMs, maxRetries);
378
394
  if (Array.isArray(data) && data.length > 0) {
379
- const result = {
395
+ return structuredResult({
380
396
  codigo: args.codigo,
381
397
  nome: `Série ${args.codigo}`,
382
- ultimoValor: { data: data[0].data, valor: parseFloat(data[0].valor) },
383
398
  fonte: "Banco Central do Brasil",
399
+ ultimoValor: { data: data[0].data, valor: parseFloat(data[0].valor) },
384
400
  urlConsulta: `${BCB_API_BASE}.${args.codigo}/dados?formato=json`,
385
401
  observacao: "Série encontrada, mas metadados detalhados não disponíveis"
386
- };
387
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
402
+ });
388
403
  }
389
404
  throw new Error("Série não encontrada");
390
405
  }
@@ -409,13 +424,12 @@ export async function handleSeriesPopulares(args) {
409
424
  porCategoria[serie.categoria] = [];
410
425
  porCategoria[serie.categoria].push(serie);
411
426
  }
412
- const result = {
427
+ return structuredResult({
413
428
  totalSeries: series.length,
414
429
  categorias: Object.keys(porCategoria).length,
415
430
  series: args.categoria ? series : porCategoria,
416
431
  observacao: "Use bcb_serie_valores ou bcb_serie_ultimos com o código para consultar os dados"
417
- };
418
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
432
+ });
419
433
  }
420
434
  catch (error) {
421
435
  return {
@@ -430,20 +444,15 @@ export async function handleBuscarSerie(args) {
430
444
  const encontradas = SERIES_POPULARES.filter(s => normalizeString(s.nome).includes(termoNorm) ||
431
445
  normalizeString(s.categoria).includes(termoNorm));
432
446
  if (encontradas.length === 0) {
433
- return {
434
- content: [{
435
- type: "text",
436
- text: JSON.stringify({
437
- termo: args.termo,
438
- totalEncontradas: 0,
439
- mensagem: "Nenhuma série encontrada no catálogo interno. Use o portal SGS do BCB para buscar outras séries: https://www3.bcb.gov.br/sgspub/",
440
- sugestao: "Tente termos como: selic, ipca, dolar, cambio, pib, inflacao, credito, emprego"
441
- }, null, 2)
442
- }]
443
- };
447
+ return structuredResult({
448
+ termo: args.termo,
449
+ totalEncontradas: 0,
450
+ series: [],
451
+ mensagem: "Nenhuma série encontrada no catálogo interno. Use o portal SGS do BCB para buscar outras séries: https://www3.bcb.gov.br/sgspub/",
452
+ sugestao: "Tente termos como: selic, ipca, dolar, cambio, pib, inflacao, credito, emprego"
453
+ });
444
454
  }
445
- const result = { termo: args.termo, totalEncontradas: encontradas.length, series: encontradas };
446
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
455
+ return structuredResult({ termo: args.termo, totalEncontradas: encontradas.length, series: encontradas });
447
456
  }
448
457
  catch (error) {
449
458
  return {
@@ -474,12 +483,7 @@ export async function handleIndicadoresAtuais(_args, timeoutMs, maxRetries) {
474
483
  return { indicador: ind.nome, codigo: ind.codigo, erro: err instanceof Error ? err.message : "Erro desconhecido" };
475
484
  }
476
485
  }));
477
- return {
478
- content: [{
479
- type: "text",
480
- text: JSON.stringify({ consultadoEm: new Date().toISOString(), indicadores: resultados }, null, 2)
481
- }]
482
- };
486
+ return structuredResult({ consultadoEm: new Date().toISOString(), indicadores: resultados });
483
487
  }
484
488
  catch (error) {
485
489
  return {
@@ -505,7 +509,8 @@ export async function handleVariacao(args, timeoutMs, maxRetries) {
505
509
  }
506
510
  if (!Array.isArray(data) || data.length < 2) {
507
511
  return {
508
- content: [{ type: "text", text: `Dados insuficientes para calcular variação. São necessários pelo menos 2 valores.` }]
512
+ content: [{ type: "text", text: `Dados insuficientes para calcular variação. São necessários pelo menos 2 valores.` }],
513
+ isError: true
509
514
  };
510
515
  }
511
516
  const serieInfo = SERIES_POPULARES.find(s => s.codigo === args.codigo);
@@ -517,7 +522,7 @@ export async function handleVariacao(args, timeoutMs, maxRetries) {
517
522
  const maximo = Math.max(...valores);
518
523
  const minimo = Math.min(...valores);
519
524
  const media = valores.reduce((a, b) => a + b, 0) / valores.length;
520
- const result = {
525
+ return structuredResult({
521
526
  serie: { codigo: args.codigo, nome: serieInfo?.nome || `Série ${args.codigo}`, categoria: serieInfo?.categoria || "Desconhecida" },
522
527
  periodo: { dataInicial: data[0].data, dataFinal: data[data.length - 1].data, totalPeriodos: data.length },
523
528
  analise: {
@@ -532,8 +537,7 @@ export async function handleVariacao(args, timeoutMs, maxRetries) {
532
537
  media: Number(media.toFixed(4)),
533
538
  amplitude: Number((maximo - minimo).toFixed(4))
534
539
  }
535
- };
536
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
540
+ });
537
541
  }
538
542
  catch (error) {
539
543
  return {
@@ -584,15 +588,14 @@ export async function handleComparar(args, timeoutMs, maxRetries) {
584
588
  const varB = "variacaoPercentual" in b && typeof b.variacaoPercentual === "number" ? b.variacaoPercentual : 0;
585
589
  return varB - varA;
586
590
  });
587
- const result = {
591
+ return structuredResult({
588
592
  periodo: { dataInicial: formatDateForApi(args.dataInicial), dataFinal: formatDateForApi(args.dataFinal) },
589
593
  totalSeries: args.codigos.length,
590
594
  seriesComDados: seriesComDados.length,
591
595
  seriesComErro: seriesComErro.length,
592
596
  ranking: seriesOrdenadas.map((s, i) => ({ posicao: i + 1, ...s })),
593
- erros: seriesComErro.length > 0 ? seriesComErro : undefined
594
- };
595
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
597
+ erros: seriesComErro.length > 0 ? seriesComErro : []
598
+ });
596
599
  }
597
600
  catch (error) {
598
601
  return {
@@ -601,6 +604,28 @@ export async function handleComparar(args, timeoutMs, maxRetries) {
601
604
  };
602
605
  }
603
606
  }
607
+ // ==================== OUTPUT SCHEMAS (JSON Schema, for worker JSON-RPC) ====================
608
+ // Shared fragment: identification block for a BCB time series.
609
+ const SERIE_REF_SCHEMA = {
610
+ type: "object",
611
+ description: "Identificação da série temporal",
612
+ properties: {
613
+ codigo: { type: "number", description: "Código da série no SGS/BCB" },
614
+ nome: { type: "string", description: "Nome da série" },
615
+ categoria: { type: "string", description: "Categoria econômica" },
616
+ periodicidade: { type: "string", description: "Periodicidade (Diária, Mensal, etc.)" }
617
+ },
618
+ required: ["codigo", "nome"]
619
+ };
620
+ // Shared fragment: a single observation (date + numeric value).
621
+ const OBSERVACAO_SCHEMA = {
622
+ type: "object",
623
+ properties: {
624
+ data: { type: "string", description: "Data da observação (dd/MM/yyyy)" },
625
+ valor: { type: "number", description: "Valor numérico da observação" }
626
+ },
627
+ required: ["data", "valor"]
628
+ };
604
629
  // ==================== TOOL DEFINITIONS (for worker JSON-RPC) ====================
605
630
  export const TOOL_DEFINITIONS = [
606
631
  {
@@ -614,6 +639,18 @@ export const TOOL_DEFINITIONS = [
614
639
  dataFinal: { type: "string", description: "Data final no formato yyyy-MM-dd ou dd/MM/yyyy (opcional)" }
615
640
  },
616
641
  required: ["codigo"]
642
+ },
643
+ outputSchema: {
644
+ type: "object",
645
+ properties: {
646
+ serie: SERIE_REF_SCHEMA,
647
+ totalRegistros: { type: "number", description: "Quantidade de observações retornadas" },
648
+ periodoInicial: { type: "string", description: "Data da primeira observação" },
649
+ periodoFinal: { type: "string", description: "Data da última observação" },
650
+ dados: { type: "array", description: "Observações históricas", items: OBSERVACAO_SCHEMA },
651
+ observacao: { type: "string", description: "Mensagem informativa (ex.: quando não há dados)" }
652
+ },
653
+ required: ["serie", "totalRegistros", "dados"]
617
654
  }
618
655
  },
619
656
  {
@@ -626,6 +663,16 @@ export const TOOL_DEFINITIONS = [
626
663
  quantidade: { type: "number", description: "Quantidade de valores a retornar (1-1000, padrão: 10)" }
627
664
  },
628
665
  required: ["codigo"]
666
+ },
667
+ outputSchema: {
668
+ type: "object",
669
+ properties: {
670
+ serie: SERIE_REF_SCHEMA,
671
+ totalRegistros: { type: "number", description: "Quantidade de observações retornadas" },
672
+ dados: { type: "array", description: "Observações mais recentes", items: OBSERVACAO_SCHEMA },
673
+ observacao: { type: "string", description: "Mensagem informativa (ex.: quando não há dados)" }
674
+ },
675
+ required: ["serie", "totalRegistros", "dados"]
629
676
  }
630
677
  },
631
678
  {
@@ -637,6 +684,23 @@ export const TOOL_DEFINITIONS = [
637
684
  codigo: { type: "number", description: "Código da série no SGS/BCB" }
638
685
  },
639
686
  required: ["codigo"]
687
+ },
688
+ outputSchema: {
689
+ type: "object",
690
+ properties: {
691
+ codigo: { type: "number", description: "Código da série no SGS/BCB" },
692
+ nome: { type: "string", description: "Nome da série" },
693
+ unidade: { type: "string", description: "Unidade de medida" },
694
+ periodicidade: { type: "string", description: "Periodicidade da série" },
695
+ fonte: { type: "string", description: "Fonte dos dados" },
696
+ categoria: { type: "string", description: "Categoria econômica" },
697
+ especial: { type: "boolean", description: "Indica se é uma série especial" },
698
+ ultimoValor: { ...OBSERVACAO_SCHEMA, description: "Última observação disponível (quando metadados detalhados não existem)" },
699
+ urlConsulta: { type: "string", description: "URL da API do BCB para consulta completa" },
700
+ urlUltimos10: { type: "string", description: "URL da API do BCB para os últimos 10 valores" },
701
+ observacao: { type: "string", description: "Observação sobre a origem dos metadados" }
702
+ },
703
+ required: ["codigo", "nome", "fonte"]
640
704
  }
641
705
  },
642
706
  {
@@ -647,6 +711,18 @@ export const TOOL_DEFINITIONS = [
647
711
  properties: {
648
712
  categoria: { type: "string", description: "Filtrar por categoria: Juros, Inflação, Câmbio, Atividade Econômica, Emprego, Fiscal, Setor Externo, Crédito, Agregados Monetários, Poupança, Índices de Mercado, Expectativas" }
649
713
  }
714
+ },
715
+ outputSchema: {
716
+ type: "object",
717
+ properties: {
718
+ totalSeries: { type: "number", description: "Quantidade total de séries retornadas" },
719
+ categorias: { type: "number", description: "Quantidade de categorias distintas" },
720
+ series: {
721
+ description: "Séries encontradas. Objeto agrupado por categoria quando sem filtro; array plano quando filtrado por categoria. Cada item contém codigo, nome, categoria e periodicidade."
722
+ },
723
+ observacao: { type: "string", description: "Dica de uso" }
724
+ },
725
+ required: ["totalSeries", "categorias", "series"]
650
726
  }
651
727
  },
652
728
  {
@@ -658,6 +734,30 @@ export const TOOL_DEFINITIONS = [
658
734
  termo: { type: "string", description: "Termo de busca (mínimo 2 caracteres)" }
659
735
  },
660
736
  required: ["termo"]
737
+ },
738
+ outputSchema: {
739
+ type: "object",
740
+ properties: {
741
+ termo: { type: "string", description: "Termo pesquisado" },
742
+ totalEncontradas: { type: "number", description: "Quantidade de séries encontradas" },
743
+ series: {
744
+ type: "array",
745
+ description: "Séries que correspondem ao termo",
746
+ items: {
747
+ type: "object",
748
+ properties: {
749
+ codigo: { type: "number" },
750
+ nome: { type: "string" },
751
+ categoria: { type: "string" },
752
+ periodicidade: { type: "string" }
753
+ },
754
+ required: ["codigo", "nome"]
755
+ }
756
+ },
757
+ mensagem: { type: "string", description: "Mensagem exibida quando nada é encontrado" },
758
+ sugestao: { type: "string", description: "Sugestões de termos alternativos" }
759
+ },
760
+ required: ["termo", "totalEncontradas", "series"]
661
761
  }
662
762
  },
663
763
  {
@@ -666,6 +766,28 @@ export const TOOL_DEFINITIONS = [
666
766
  inputSchema: {
667
767
  type: "object",
668
768
  properties: {}
769
+ },
770
+ outputSchema: {
771
+ type: "object",
772
+ properties: {
773
+ consultadoEm: { type: "string", description: "Timestamp ISO 8601 da consulta" },
774
+ indicadores: {
775
+ type: "array",
776
+ description: "Lista de indicadores com seus valores mais recentes",
777
+ items: {
778
+ type: "object",
779
+ properties: {
780
+ indicador: { type: "string", description: "Nome do indicador" },
781
+ codigo: { type: "number", description: "Código da série no SGS/BCB" },
782
+ data: { type: "string", description: "Data da observação" },
783
+ valor: { type: "number", description: "Valor mais recente" },
784
+ erro: { type: "string", description: "Mensagem de erro quando o indicador não pôde ser obtido" }
785
+ },
786
+ required: ["indicador", "codigo"]
787
+ }
788
+ }
789
+ },
790
+ required: ["consultadoEm", "indicadores"]
669
791
  }
670
792
  },
671
793
  {
@@ -680,6 +802,55 @@ export const TOOL_DEFINITIONS = [
680
802
  periodos: { type: "number", description: "Alternativa: calcular variação dos últimos N períodos (ignora datas se informado)" }
681
803
  },
682
804
  required: ["codigo"]
805
+ },
806
+ outputSchema: {
807
+ type: "object",
808
+ properties: {
809
+ serie: {
810
+ type: "object",
811
+ description: "Identificação da série",
812
+ properties: {
813
+ codigo: { type: "number" },
814
+ nome: { type: "string" },
815
+ categoria: { type: "string" }
816
+ },
817
+ required: ["codigo", "nome"]
818
+ },
819
+ periodo: {
820
+ type: "object",
821
+ description: "Janela temporal analisada",
822
+ properties: {
823
+ dataInicial: { type: "string" },
824
+ dataFinal: { type: "string" },
825
+ totalPeriodos: { type: "number" }
826
+ },
827
+ required: ["dataInicial", "dataFinal", "totalPeriodos"]
828
+ },
829
+ analise: {
830
+ type: "object",
831
+ description: "Resultado da variação entre o primeiro e o último valor",
832
+ properties: {
833
+ valorInicial: { type: "number" },
834
+ valorFinal: { type: "number" },
835
+ diferencaAbsoluta: { type: "number" },
836
+ variacaoPercentual: { type: "number" },
837
+ variacaoFormatada: { type: "string" }
838
+ },
839
+ required: ["valorInicial", "valorFinal", "variacaoPercentual"]
840
+ },
841
+ estatisticas: {
842
+ type: "object",
843
+ description: "Estatísticas descritivas dos valores no período",
844
+ properties: {
845
+ maximo: { type: "number" },
846
+ minimo: { type: "number" },
847
+ media: { type: "number" },
848
+ amplitude: { type: "number" }
849
+ },
850
+ required: ["maximo", "minimo", "media", "amplitude"]
851
+ }
852
+ },
853
+ required: ["serie", "periodo", "analise", "estatisticas"]
683
854
  }
684
855
  },
685
856
  {
@@ -693,6 +864,60 @@ export const TOOL_DEFINITIONS = [
693
864
  dataFinal: { type: "string", description: "Data final (yyyy-MM-dd ou dd/MM/yyyy)" }
694
865
  },
695
866
  required: ["codigos", "dataInicial", "dataFinal"]
867
+ },
868
+ outputSchema: {
869
+ type: "object",
870
+ properties: {
871
+ periodo: {
872
+ type: "object",
873
+ description: "Janela temporal comparada",
874
+ properties: {
875
+ dataInicial: { type: "string" },
876
+ dataFinal: { type: "string" }
877
+ },
878
+ required: ["dataInicial", "dataFinal"]
879
+ },
880
+ totalSeries: { type: "number", description: "Quantidade de séries solicitadas" },
881
+ seriesComDados: { type: "number", description: "Quantidade de séries com dados no período" },
882
+ seriesComErro: { type: "number", description: "Quantidade de séries sem dados ou com erro" },
883
+ ranking: {
884
+ type: "array",
885
+ description: "Séries ordenadas pela variação percentual (maior para menor)",
886
+ items: {
887
+ type: "object",
888
+ properties: {
889
+ posicao: { type: "number", description: "Posição no ranking" },
890
+ codigo: { type: "number" },
891
+ nome: { type: "string" },
892
+ categoria: { type: "string" },
893
+ periodicidade: { type: "string" },
894
+ totalRegistros: { type: "number" },
895
+ valorInicial: { type: "number" },
896
+ valorFinal: { type: "number" },
897
+ variacaoPercentual: { type: "number" },
898
+ variacaoFormatada: { type: "string" },
899
+ maximo: { type: "number" },
900
+ minimo: { type: "number" },
901
+ media: { type: "number" }
902
+ },
903
+ required: ["posicao", "codigo", "nome"]
904
+ }
905
+ },
906
+ erros: {
907
+ type: "array",
908
+ description: "Séries que não retornaram dados, com o motivo",
909
+ items: {
910
+ type: "object",
911
+ properties: {
912
+ codigo: { type: "number" },
913
+ nome: { type: "string" },
914
+ erro: { type: "string" }
915
+ },
916
+ required: ["codigo", "erro"]
917
+ }
918
+ }
919
+ },
920
+ required: ["periodo", "totalSeries", "seriesComDados", "seriesComErro", "ranking"]
696
921
  }
697
922
  }
698
923
  ];