bcb-br-mcp 1.2.1 → 1.3.1

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.1"
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.1"
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,11 +604,40 @@ 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
  {
607
632
  name: "bcb_serie_valores",
608
633
  description: "Consulta valores de uma série temporal do BCB por código. Retorna dados históricos com data e valor.",
634
+ annotations: {
635
+ title: "Consultar valores da série",
636
+ readOnlyHint: true,
637
+ destructiveHint: false,
638
+ idempotentHint: true,
639
+ openWorldHint: true
640
+ },
609
641
  inputSchema: {
610
642
  type: "object",
611
643
  properties: {
@@ -614,11 +646,30 @@ export const TOOL_DEFINITIONS = [
614
646
  dataFinal: { type: "string", description: "Data final no formato yyyy-MM-dd ou dd/MM/yyyy (opcional)" }
615
647
  },
616
648
  required: ["codigo"]
649
+ },
650
+ outputSchema: {
651
+ type: "object",
652
+ properties: {
653
+ serie: SERIE_REF_SCHEMA,
654
+ totalRegistros: { type: "number", description: "Quantidade de observações retornadas" },
655
+ periodoInicial: { type: "string", description: "Data da primeira observação" },
656
+ periodoFinal: { type: "string", description: "Data da última observação" },
657
+ dados: { type: "array", description: "Observações históricas", items: OBSERVACAO_SCHEMA },
658
+ observacao: { type: "string", description: "Mensagem informativa (ex.: quando não há dados)" }
659
+ },
660
+ required: ["serie", "totalRegistros", "dados"]
617
661
  }
618
662
  },
619
663
  {
620
664
  name: "bcb_serie_ultimos",
621
665
  description: "Obtém os últimos N valores de uma série temporal do BCB. Útil para consultar dados mais recentes.",
666
+ annotations: {
667
+ title: "Últimos valores da série",
668
+ readOnlyHint: true,
669
+ destructiveHint: false,
670
+ idempotentHint: true,
671
+ openWorldHint: true
672
+ },
622
673
  inputSchema: {
623
674
  type: "object",
624
675
  properties: {
@@ -626,51 +677,171 @@ export const TOOL_DEFINITIONS = [
626
677
  quantidade: { type: "number", description: "Quantidade de valores a retornar (1-1000, padrão: 10)" }
627
678
  },
628
679
  required: ["codigo"]
680
+ },
681
+ outputSchema: {
682
+ type: "object",
683
+ properties: {
684
+ serie: SERIE_REF_SCHEMA,
685
+ totalRegistros: { type: "number", description: "Quantidade de observações retornadas" },
686
+ dados: { type: "array", description: "Observações mais recentes", items: OBSERVACAO_SCHEMA },
687
+ observacao: { type: "string", description: "Mensagem informativa (ex.: quando não há dados)" }
688
+ },
689
+ required: ["serie", "totalRegistros", "dados"]
629
690
  }
630
691
  },
631
692
  {
632
693
  name: "bcb_serie_metadados",
633
694
  description: "Obtém informações/metadados de uma série temporal do BCB. Retorna nome, periodicidade, categoria e outros detalhes.",
695
+ annotations: {
696
+ title: "Metadados da série",
697
+ readOnlyHint: true,
698
+ destructiveHint: false,
699
+ idempotentHint: true,
700
+ openWorldHint: true
701
+ },
634
702
  inputSchema: {
635
703
  type: "object",
636
704
  properties: {
637
705
  codigo: { type: "number", description: "Código da série no SGS/BCB" }
638
706
  },
639
707
  required: ["codigo"]
708
+ },
709
+ outputSchema: {
710
+ type: "object",
711
+ properties: {
712
+ codigo: { type: "number", description: "Código da série no SGS/BCB" },
713
+ nome: { type: "string", description: "Nome da série" },
714
+ unidade: { type: "string", description: "Unidade de medida" },
715
+ periodicidade: { type: "string", description: "Periodicidade da série" },
716
+ fonte: { type: "string", description: "Fonte dos dados" },
717
+ categoria: { type: "string", description: "Categoria econômica" },
718
+ especial: { type: "boolean", description: "Indica se é uma série especial" },
719
+ ultimoValor: { ...OBSERVACAO_SCHEMA, description: "Última observação disponível (quando metadados detalhados não existem)" },
720
+ urlConsulta: { type: "string", description: "URL da API do BCB para consulta completa" },
721
+ urlUltimos10: { type: "string", description: "URL da API do BCB para os últimos 10 valores" },
722
+ observacao: { type: "string", description: "Observação sobre a origem dos metadados" }
723
+ },
724
+ required: ["codigo", "nome", "fonte"]
640
725
  }
641
726
  },
642
727
  {
643
728
  name: "bcb_series_populares",
644
729
  description: "Lista 150+ séries temporais do BCB com seus códigos. Inclui juros, inflação, câmbio, PIB, emprego, crédito e outros indicadores econômicos.",
730
+ annotations: {
731
+ title: "Listar séries populares",
732
+ readOnlyHint: true,
733
+ destructiveHint: false,
734
+ idempotentHint: true,
735
+ openWorldHint: false
736
+ },
645
737
  inputSchema: {
646
738
  type: "object",
647
739
  properties: {
648
740
  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
741
  }
742
+ },
743
+ outputSchema: {
744
+ type: "object",
745
+ properties: {
746
+ totalSeries: { type: "number", description: "Quantidade total de séries retornadas" },
747
+ categorias: { type: "number", description: "Quantidade de categorias distintas" },
748
+ series: {
749
+ 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."
750
+ },
751
+ observacao: { type: "string", description: "Dica de uso" }
752
+ },
753
+ required: ["totalSeries", "categorias", "series"]
650
754
  }
651
755
  },
652
756
  {
653
757
  name: "bcb_buscar_serie",
654
758
  description: "Busca séries no catálogo interno por nome ou descrição. Aceita termos com ou sem acentos (ex: 'inflacao' encontra 'Inflação').",
759
+ annotations: {
760
+ title: "Buscar série no catálogo",
761
+ readOnlyHint: true,
762
+ destructiveHint: false,
763
+ idempotentHint: true,
764
+ openWorldHint: false
765
+ },
655
766
  inputSchema: {
656
767
  type: "object",
657
768
  properties: {
658
769
  termo: { type: "string", description: "Termo de busca (mínimo 2 caracteres)" }
659
770
  },
660
771
  required: ["termo"]
772
+ },
773
+ outputSchema: {
774
+ type: "object",
775
+ properties: {
776
+ termo: { type: "string", description: "Termo pesquisado" },
777
+ totalEncontradas: { type: "number", description: "Quantidade de séries encontradas" },
778
+ series: {
779
+ type: "array",
780
+ description: "Séries que correspondem ao termo",
781
+ items: {
782
+ type: "object",
783
+ properties: {
784
+ codigo: { type: "number" },
785
+ nome: { type: "string" },
786
+ categoria: { type: "string" },
787
+ periodicidade: { type: "string" }
788
+ },
789
+ required: ["codigo", "nome"]
790
+ }
791
+ },
792
+ mensagem: { type: "string", description: "Mensagem exibida quando nada é encontrado" },
793
+ sugestao: { type: "string", description: "Sugestões de termos alternativos" }
794
+ },
795
+ required: ["termo", "totalEncontradas", "series"]
661
796
  }
662
797
  },
663
798
  {
664
799
  name: "bcb_indicadores_atuais",
665
800
  description: "Obtém os valores mais recentes dos principais indicadores econômicos: Selic, IPCA, Dólar PTAX e IBC-Br.",
801
+ annotations: {
802
+ title: "Indicadores econômicos atuais",
803
+ readOnlyHint: true,
804
+ destructiveHint: false,
805
+ idempotentHint: true,
806
+ openWorldHint: true
807
+ },
666
808
  inputSchema: {
667
809
  type: "object",
668
810
  properties: {}
811
+ },
812
+ outputSchema: {
813
+ type: "object",
814
+ properties: {
815
+ consultadoEm: { type: "string", description: "Timestamp ISO 8601 da consulta" },
816
+ indicadores: {
817
+ type: "array",
818
+ description: "Lista de indicadores com seus valores mais recentes",
819
+ items: {
820
+ type: "object",
821
+ properties: {
822
+ indicador: { type: "string", description: "Nome do indicador" },
823
+ codigo: { type: "number", description: "Código da série no SGS/BCB" },
824
+ data: { type: "string", description: "Data da observação" },
825
+ valor: { type: "number", description: "Valor mais recente" },
826
+ erro: { type: "string", description: "Mensagem de erro quando o indicador não pôde ser obtido" }
827
+ },
828
+ required: ["indicador", "codigo"]
829
+ }
830
+ }
831
+ },
832
+ required: ["consultadoEm", "indicadores"]
669
833
  }
670
834
  },
671
835
  {
672
836
  name: "bcb_variacao",
673
837
  description: "Calcula a variação percentual de uma série entre duas datas ou nos últimos N períodos. Útil para análise de tendências.",
838
+ annotations: {
839
+ title: "Variação percentual da série",
840
+ readOnlyHint: true,
841
+ destructiveHint: false,
842
+ idempotentHint: true,
843
+ openWorldHint: true
844
+ },
674
845
  inputSchema: {
675
846
  type: "object",
676
847
  properties: {
@@ -680,11 +851,67 @@ export const TOOL_DEFINITIONS = [
680
851
  periodos: { type: "number", description: "Alternativa: calcular variação dos últimos N períodos (ignora datas se informado)" }
681
852
  },
682
853
  required: ["codigo"]
854
+ },
855
+ outputSchema: {
856
+ type: "object",
857
+ properties: {
858
+ serie: {
859
+ type: "object",
860
+ description: "Identificação da série",
861
+ properties: {
862
+ codigo: { type: "number" },
863
+ nome: { type: "string" },
864
+ categoria: { type: "string" }
865
+ },
866
+ required: ["codigo", "nome"]
867
+ },
868
+ periodo: {
869
+ type: "object",
870
+ description: "Janela temporal analisada",
871
+ properties: {
872
+ dataInicial: { type: "string" },
873
+ dataFinal: { type: "string" },
874
+ totalPeriodos: { type: "number" }
875
+ },
876
+ required: ["dataInicial", "dataFinal", "totalPeriodos"]
877
+ },
878
+ analise: {
879
+ type: "object",
880
+ description: "Resultado da variação entre o primeiro e o último valor",
881
+ properties: {
882
+ valorInicial: { type: "number" },
883
+ valorFinal: { type: "number" },
884
+ diferencaAbsoluta: { type: "number" },
885
+ variacaoPercentual: { type: "number" },
886
+ variacaoFormatada: { type: "string" }
887
+ },
888
+ required: ["valorInicial", "valorFinal", "variacaoPercentual"]
889
+ },
890
+ estatisticas: {
891
+ type: "object",
892
+ description: "Estatísticas descritivas dos valores no período",
893
+ properties: {
894
+ maximo: { type: "number" },
895
+ minimo: { type: "number" },
896
+ media: { type: "number" },
897
+ amplitude: { type: "number" }
898
+ },
899
+ required: ["maximo", "minimo", "media", "amplitude"]
900
+ }
901
+ },
902
+ required: ["serie", "periodo", "analise", "estatisticas"]
683
903
  }
684
904
  },
685
905
  {
686
906
  name: "bcb_comparar",
687
907
  description: "Compara 2 a 5 séries temporais no mesmo período. Útil para análise de correlação entre indicadores.",
908
+ annotations: {
909
+ title: "Comparar séries",
910
+ readOnlyHint: true,
911
+ destructiveHint: false,
912
+ idempotentHint: true,
913
+ openWorldHint: true
914
+ },
688
915
  inputSchema: {
689
916
  type: "object",
690
917
  properties: {
@@ -693,6 +920,60 @@ export const TOOL_DEFINITIONS = [
693
920
  dataFinal: { type: "string", description: "Data final (yyyy-MM-dd ou dd/MM/yyyy)" }
694
921
  },
695
922
  required: ["codigos", "dataInicial", "dataFinal"]
923
+ },
924
+ outputSchema: {
925
+ type: "object",
926
+ properties: {
927
+ periodo: {
928
+ type: "object",
929
+ description: "Janela temporal comparada",
930
+ properties: {
931
+ dataInicial: { type: "string" },
932
+ dataFinal: { type: "string" }
933
+ },
934
+ required: ["dataInicial", "dataFinal"]
935
+ },
936
+ totalSeries: { type: "number", description: "Quantidade de séries solicitadas" },
937
+ seriesComDados: { type: "number", description: "Quantidade de séries com dados no período" },
938
+ seriesComErro: { type: "number", description: "Quantidade de séries sem dados ou com erro" },
939
+ ranking: {
940
+ type: "array",
941
+ description: "Séries ordenadas pela variação percentual (maior para menor)",
942
+ items: {
943
+ type: "object",
944
+ properties: {
945
+ posicao: { type: "number", description: "Posição no ranking" },
946
+ codigo: { type: "number" },
947
+ nome: { type: "string" },
948
+ categoria: { type: "string" },
949
+ periodicidade: { type: "string" },
950
+ totalRegistros: { type: "number" },
951
+ valorInicial: { type: "number" },
952
+ valorFinal: { type: "number" },
953
+ variacaoPercentual: { type: "number" },
954
+ variacaoFormatada: { type: "string" },
955
+ maximo: { type: "number" },
956
+ minimo: { type: "number" },
957
+ media: { type: "number" }
958
+ },
959
+ required: ["posicao", "codigo", "nome"]
960
+ }
961
+ },
962
+ erros: {
963
+ type: "array",
964
+ description: "Séries que não retornaram dados, com o motivo",
965
+ items: {
966
+ type: "object",
967
+ properties: {
968
+ codigo: { type: "number" },
969
+ nome: { type: "string" },
970
+ erro: { type: "string" }
971
+ },
972
+ required: ["codigo", "erro"]
973
+ }
974
+ }
975
+ },
976
+ required: ["periodo", "totalSeries", "seriesComDados", "seriesComErro", "ranking"]
696
977
  }
697
978
  }
698
979
  ];