biatoolkit 1.0.3__py3-none-any.whl → 1.1.0__py3-none-any.whl

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.
biatoolkit/__init__.py CHANGED
@@ -0,0 +1,4 @@
1
+ from .util import BiaUtil
2
+ from .basic_client import BiaClient
3
+
4
+ __all__ = ["BiaUtil", "BiaClient"]
@@ -1,63 +1,141 @@
1
+ """
2
+ biatoolkit.basic_client
3
+
4
+ Este módulo contém o BiaClient, um cliente HTTP assíncrono para comunicação
5
+ com servidores MCP (Model Context Protocol).
6
+
7
+ Responsabilidades:
8
+ - Abrir e gerenciar conexões HTTP streamable com servidores MCP.
9
+ - Inicializar sessões MCP.
10
+ - Encapsular chamadas comuns (listar tools, executar tool).
11
+
12
+ O objetivo é esconder os detalhes de sessão, streams e inicialização,
13
+ expondo uma API simples para quem consome a biblioteca.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from typing import Any, Awaitable, Callable, Optional, Dict
19
+
1
20
  from mcp import ClientSession
2
21
  from mcp.client.streamable_http import streamablehttp_client
3
22
 
23
+ from .settings import BiaToolkitSettings
24
+
25
+
4
26
  class BiaClient:
5
27
  """
6
- Cliente básico para interação com o MCP (Middleware de Comunicação de Processos).
7
- Permite listar ferramentas disponíveis e executar ferramentas específicas via HTTP.
28
+ Cliente básico para interação com servidores MCP.
29
+
30
+ Esta classe encapsula toda a complexidade envolvida em:
31
+ - Abrir conexões HTTP streamable
32
+ - Criar e inicializar ClientSession
33
+ - Executar chamadas MCP
34
+
35
+ Exemplos de uso:
36
+ client = BiaClient("http://localhost:8000")
37
+ tools = await client.list_tools()
38
+ result = await client.call_tool("minha_tool", {"x": 1})
8
39
  """
9
40
 
10
- def __init__(self, url: str = "http://0.0.0.0:8000/mcp", headers: dict = None):
41
+ def __init__(
42
+ self,
43
+ url: str = "http://0.0.0.0:8000/mcp",
44
+ headers: Optional[Dict[str, str]] = None,
45
+ settings: Optional[BiaToolkitSettings] = None,
46
+ ):
11
47
  """
12
- Inicializa o BasicClient.
48
+ Inicializa o cliente MCP.
13
49
 
14
50
  Args:
15
- url (str): URL base do MCP. Se não terminar com '/mcp', será adicionado automaticamente.
16
- headers (dict): Cabeçalhos HTTP opcionais para requisições.
51
+ url:
52
+ URL base do servidor MCP.
53
+ - Se não terminar com '/mcp', o sufixo será adicionado automaticamente.
54
+ headers:
55
+ Headers HTTP opcionais enviados em todas as requisições.
56
+ Normalmente usados para enviar contexto (runtime, autenticação, etc.).
57
+ settings:
58
+ Configurações opcionais da biblioteca (timeout, etc.).
59
+ Se None, carrega defaults e overrides via variáveis de ambiente.
17
60
  """
18
- sufix = "/mcp"
61
+ # Carrega configurações globais (timeout, etc.)
62
+ self.settings = settings or BiaToolkitSettings.from_env()
63
+
19
64
  # Garante que a URL termine com '/mcp'
20
- self.url = url if url.endswith(sufix) else f"{url}{sufix}"
65
+ suffix = "/mcp"
66
+ self.url = url if url.endswith(suffix) else f"{url}{suffix}"
67
+
68
+ # Headers HTTP que serão enviados para o servidor MCP
21
69
  self.headers = headers
22
70
 
23
- async def list_tools(self) -> dict:
71
+ async def _with_session(self, fn: Callable[[ClientSession], Awaitable[Any]]) -> Any:
24
72
  """
25
- Lista as ferramentas disponíveis no MCP.
73
+ Executa uma função dentro de uma sessão MCP já inicializada.
74
+
75
+ Este método centraliza todo o boilerplate necessário para:
76
+ - Abrir a conexão HTTP streamable
77
+ - Criar a ClientSession
78
+ - Chamar session.initialize()
79
+ - Garantir fechamento correto dos recursos
80
+
81
+ Ele recebe uma função (callback) que recebe a ClientSession e
82
+ executa a lógica específica (listar tools, chamar tool, etc.).
83
+
84
+ Args:
85
+ fn: Função assíncrona que recebe uma ClientSession.
26
86
 
27
87
  Returns:
28
- dict: Dicionário contendo as ferramentas disponíveis.
29
- """
30
- # Cria um cliente HTTP streamable para comunicação assíncrona
31
- async with streamablehttp_client(self.url, self.headers, timeout=120, terminate_on_close=False) as (
32
- read_stream,
33
- write_stream,
34
- _,
35
- ):
36
- # Cria uma sessão de cliente MCP usando os streams
88
+ O valor retornado pela função fn.
89
+ """
90
+ async with streamablehttp_client(
91
+ self.url,
92
+ self.headers,
93
+ # Timeout configurável via settings
94
+ timeout=self.settings.client_timeout_seconds,
95
+ # Mantém o servidor ativo mesmo após fechar streams
96
+ terminate_on_close=False,
97
+ ) as (read_stream, write_stream, _):
98
+
99
+ # Cria a sessão MCP usando os streams
37
100
  async with ClientSession(read_stream, write_stream) as session:
38
- await session.initialize() # Inicializa a sessão
39
- tool_result = await session.list_tools() # Solicita a lista de ferramentas
40
- return tool_result
41
-
101
+ # Inicialização obrigatória do protocolo MCP
102
+ await session.initialize()
103
+
104
+ # Executa a lógica específica passada pelo caller
105
+ return await fn(session)
106
+
107
+ async def list_tools(self) -> dict:
108
+ """
109
+ Lista todas as ferramentas (tools) disponíveis no servidor MCP.
110
+
111
+ Returns:
112
+ dict: Estrutura contendo as tools expostas pelo servidor.
113
+ """
114
+
115
+ async def _call(session: ClientSession) -> Any:
116
+ return await session.list_tools()
117
+
118
+ return await self._with_session(_call)
119
+
42
120
  async def call_tool(self, tool_name: str, params: dict = None) -> dict:
43
121
  """
44
- Executa uma ferramenta específica disponível no MCP.
122
+ Executa uma ferramenta específica disponível no servidor MCP.
45
123
 
46
124
  Args:
47
- tool_name (str): Nome da ferramenta a ser executada.
48
- params (dict, opcional): Parâmetros para a execução da ferramenta.
125
+ tool_name:
126
+ Nome da tool a ser executada (exatamente como exposta pelo servidor).
127
+ params:
128
+ Parâmetros da tool, enviados como dicionário.
129
+ Pode ser None se a tool não exigir parâmetros.
49
130
 
50
131
  Returns:
51
- dict: Resultado da execução da ferramenta.
52
- """
53
- # Cria um cliente HTTP streamable para comunicação assíncrona
54
- async with streamablehttp_client(self.url, self.headers, timeout=120, terminate_on_close=False) as (
55
- read_stream,
56
- write_stream,
57
- _,
58
- ):
59
- # Cria uma sessão de cliente MCP usando os streams
60
- async with ClientSession(read_stream, write_stream) as session:
61
- await session.initialize() # Inicializa a sessão
62
- result = await session.call_tool(tool_name, params) # Executa a ferramenta
63
- return result
132
+ dict: Resultado da execução da tool.
133
+ """
134
+
135
+ async def _call(session: ClientSession) -> Any:
136
+ return await session.call_tool(tool_name, params)
137
+
138
+ return await self._with_session(_call)
139
+
140
+
141
+ __all__ = ["BiaClient"]
@@ -0,0 +1 @@
1
+ # biatoolkit/schema/__init__.py
biatoolkit/settings.py ADDED
@@ -0,0 +1,106 @@
1
+ """
2
+ biatoolkit.settings
3
+
4
+ Este módulo centraliza todas as configurações globais da Bia Toolkit.
5
+
6
+ Objetivos:
7
+ - Evitar valores hardcoded espalhados pelo código.
8
+ - Permitir override simples via variáveis de ambiente.
9
+ - Facilitar testes, manutenção e futuras extensões.
10
+
11
+ Exemplos de override via environment:
12
+ BIATOOLKIT_HEADER_PREFIX=x-amzn-bedrock-agentcore-runtime-custom
13
+ BIATOOLKIT_AWS_REGION=us-east-1
14
+ BIATOOLKIT_CLIENT_TIMEOUT_SECONDS=60
15
+ """
16
+
17
+ from dataclasses import dataclass
18
+ import os
19
+
20
+
21
+ @dataclass(frozen=True)
22
+ class BiaToolkitSettings:
23
+ """
24
+ Objeto imutável (frozen) que representa as configurações da biblioteca.
25
+
26
+ Por que usar dataclass + frozen?
27
+ - Facilita leitura e manutenção.
28
+ - Garante que as configurações não sejam alteradas em runtime,
29
+ evitando efeitos colaterais difíceis de rastrear.
30
+ """
31
+
32
+ # ------------------------------------------------------------------
33
+ # Server / Headers
34
+ # ------------------------------------------------------------------
35
+
36
+ # Prefixo base dos headers customizados aceitos pelo runtime do AgentCore.
37
+ # Exemplo final:
38
+ # x-amzn-bedrock-agentcore-runtime-custom-user-email
39
+ header_prefix: str = "x-amzn-bedrock-agentcore-runtime-custom"
40
+
41
+ # ------------------------------------------------------------------
42
+ # AWS
43
+ # ------------------------------------------------------------------
44
+
45
+ # Região AWS usada para acessar serviços como SSM Parameter Store.
46
+ # Default alinhado com o ambiente do Bia Agent Builder.
47
+ aws_region: str = "sa-east-1"
48
+
49
+ # ------------------------------------------------------------------
50
+ # Client (MCP HTTP Client)
51
+ # ------------------------------------------------------------------
52
+
53
+ # Timeout padrão (em segundos) para chamadas HTTP ao servidor MCP.
54
+ # Evita requests presos indefinidamente em ambientes instáveis.
55
+ client_timeout_seconds: int = 120
56
+
57
+ # ------------------------------------------------------------------
58
+ # Factory methods
59
+ # ------------------------------------------------------------------
60
+
61
+ @staticmethod
62
+ def from_env() -> "BiaToolkitSettings":
63
+ """
64
+ Cria uma instância de BiaToolkitSettings a partir de variáveis de ambiente.
65
+
66
+ Comportamento:
67
+ - Cada configuração pode ser sobrescrita individualmente via env.
68
+ - Caso a variável não exista ou seja inválida, usa o valor default.
69
+
70
+ Variáveis suportadas:
71
+ - BIATOOLKIT_HEADER_PREFIX
72
+ - BIATOOLKIT_AWS_REGION
73
+ - BIATOOLKIT_CLIENT_TIMEOUT_SECONDS
74
+
75
+ Returns:
76
+ BiaToolkitSettings: instância configurada.
77
+ """
78
+
79
+ # Header prefix (string simples)
80
+ header_prefix = os.getenv(
81
+ "BIATOOLKIT_HEADER_PREFIX",
82
+ "x-amzn-bedrock-agentcore-runtime-custom",
83
+ )
84
+
85
+ # Região AWS
86
+ aws_region = os.getenv(
87
+ "BIATOOLKIT_AWS_REGION",
88
+ "sa-east-1",
89
+ )
90
+
91
+ # Timeout do client (conversão segura para int)
92
+ timeout_str = os.getenv(
93
+ "BIATOOLKIT_CLIENT_TIMEOUT_SECONDS",
94
+ "120",
95
+ )
96
+ try:
97
+ timeout = int(timeout_str)
98
+ except ValueError:
99
+ # Se o valor não for um inteiro válido, cai no default
100
+ timeout = 120
101
+
102
+ return BiaToolkitSettings(
103
+ header_prefix=header_prefix,
104
+ aws_region=aws_region,
105
+ client_timeout_seconds=timeout,
106
+ )
biatoolkit/util.py CHANGED
@@ -1,79 +1,228 @@
1
+ """
2
+ biatoolkit.util
3
+
4
+ Este módulo contém a classe BiaUtil, uma "fachada" (facade) com utilidades comuns
5
+ para MCP Servers no ecossistema Bia Agent Builder.
6
+
7
+ Responsabilidades principais:
8
+ - Ler e interpretar headers padronizados enviados no runtime (AWS Bedrock AgentCore).
9
+ - Buscar parâmetros de configuração/segredos primeiro no ambiente (.env/variáveis),
10
+ e como fallback no AWS SSM Parameter Store (cofre de segredos no ambiente produtivo).
11
+ """
12
+
13
+ from typing import Optional
14
+ import os
15
+
16
+ import boto3
1
17
  from mcp.server.fastmcp import FastMCP
18
+
19
+ from .settings import BiaToolkitSettings
2
20
  from .schema.header import Header
3
21
 
4
- import boto3
5
- import os
6
22
 
7
- class BiaUtil():
23
+ class BiaUtil:
24
+ """
25
+ Classe utilitária para uso dentro de um MCP Server.
26
+
27
+ Exemplos de uso:
28
+ util = BiaUtil(mcp)
29
+ header = util.get_header()
30
+ token = util.get_parameter("MEU_TOKEN")
8
31
 
32
+ Observações:
33
+ - Esta classe depende do contexto de requisição do FastMCP (mcp.get_context()).
34
+ - Em produção (AgentCore), apenas alguns headers são repassados pelo runtime.
35
+ """
36
+
37
+ # Prefixo base dos headers customizados aceitos no runtime do AgentCore.
38
+ # Exemplo de header final: "x-amzn-bedrock-agentcore-runtime-custom-user-email"
9
39
  HEADER_PREFIX = "x-amzn-bedrock-agentcore-runtime-custom"
10
40
 
11
- def __init__(self, mcp: FastMCP):
41
+ def __init__(self, mcp: FastMCP, settings: Optional[BiaToolkitSettings] = None):
12
42
  """
13
- Inicializa o utilitário BiaUtil com uma instância do FastMCP.
43
+ Inicializa o utilitário.
14
44
 
15
45
  Args:
16
- mcp (FastMCP): Instância do servidor FastMCP para obter contexto da requisição.
46
+ mcp: Instância do FastMCP, usada para acessar o contexto da requisição.
47
+ settings: Configurações opcionais (region, timeout, header_prefix).
48
+ Se None, carrega defaults e overrides via variáveis de ambiente.
17
49
  """
18
50
  self.mcp = mcp
19
51
 
52
+ # Settings podem vir explicitamente (testes/uso avançado) ou via environment.
53
+ self.settings = settings or BiaToolkitSettings.from_env()
54
+
55
+ # Permite sobrescrever o prefixo dos headers via settings.
56
+ # Mantém compatibilidade: self.HEADER_PREFIX é usado na composição das chaves.
57
+ self.HEADER_PREFIX = self.settings.header_prefix
58
+
59
+ def _headers(self) -> dict:
60
+ """
61
+ Obtém o dicionário de headers da requisição atual via contexto do MCP.
62
+
63
+ Returns:
64
+ dict: Headers presentes na requisição (ou {} se ausentes).
65
+ """
66
+ ctx = self.mcp.get_context()
67
+ # Estrutura esperada no FastMCP: ctx.request_context.request.headers
68
+ return ctx.request_context.request.headers or {}
69
+
70
+ def _h(self, suffix: str):
71
+ """
72
+ Lê um header customizado do runtime, dado o sufixo.
73
+
74
+ Exemplo:
75
+ suffix="user-email" -> lê "x-amzn-bedrock-agentcore-runtime-custom-user-email"
76
+
77
+ Args:
78
+ suffix: Parte final do nome do header.
79
+
80
+ Returns:
81
+ O valor do header (str) ou None.
82
+ """
83
+ return self._headers().get(f"{self.HEADER_PREFIX}-{suffix}", None)
84
+
85
+ def _to_int(self, value, default: int = 0) -> int:
86
+ """
87
+ Converte um valor para int de forma segura.
88
+
89
+ Por quê:
90
+ - Headers podem vir como None, string vazia ou valores inválidos ("abc").
91
+ - Este método evita exceptions e padroniza o fallback para 'default'.
92
+
93
+ Args:
94
+ value: valor a converter.
95
+ default: valor retornado caso não seja possível converter.
96
+
97
+ Returns:
98
+ int: valor convertido ou default.
99
+ """
100
+ try:
101
+ if value is None:
102
+ return default
103
+ if isinstance(value, str) and value.strip() == "":
104
+ return default
105
+ return int(value)
106
+ except (TypeError, ValueError):
107
+ return default
108
+
20
109
  def __get_from_ssm(self, parameter_name: str) -> str:
21
110
  """
22
111
  Busca o valor de um parâmetro no AWS SSM Parameter Store.
23
112
 
113
+ Como funciona:
114
+ - O runtime envia um header "...-prefix" que define a "pasta" (path) base dos segredos.
115
+ - O nome final do parâmetro no SSM fica: "{prefix}/{parameter_name}"
116
+ - WithDecryption=True permite ler SecureString.
117
+
118
+ Importante:
119
+ - Se não houver prefix no header, retorna None (não tenta chamar AWS).
120
+ Isso evita chamadas inválidas como "None/MEU_PARAM".
121
+
24
122
  Args:
25
- parameter_name (str): Nome do parâmetro a ser buscado.
123
+ parameter_name: Nome do parâmetro a ser buscado.
26
124
 
27
125
  Returns:
28
- str: Valor do parâmetro, ou None se não encontrado.
126
+ str | None: Valor do parâmetro, ou None se não encontrado/sem prefix.
29
127
  """
30
- ctx = self.mcp.get_context() # Obtém o contexto da requisição atual
31
- headers = ctx.request_context.request.headers # Acessa os headers da requisição
32
- prefix = headers.get(f"{self.HEADER_PREFIX}-prefix", None) # Prefixo customizado do header
33
- client = boto3.client('ssm', region_name="sa-east-1") # Cria cliente SSM na região especificada
128
+ # Obtém headers do contexto do MCP
129
+ headers = self._headers()
130
+
131
+ # Prefixo customizado do header que aponta para a "pasta" de segredos
132
+ prefix = headers.get(f"{self.HEADER_PREFIX}-prefix", None)
133
+
134
+ # Sem prefix não é possível montar o path no SSM; evita chamadas inválidas.
135
+ if not prefix:
136
+ return None
137
+
138
+ # Cria cliente SSM na região configurada (default: sa-east-1)
139
+ client = boto3.client("ssm", region_name=self.settings.aws_region)
140
+
34
141
  try:
35
142
  response = client.get_parameter(
36
143
  Name=f"{prefix}/{parameter_name}",
37
- WithDecryption=True
144
+ WithDecryption=True,
38
145
  )
39
146
  except client.exceptions.ParameterNotFound:
40
- return None # Retorna None se o parâmetro não for encontrado
41
- return response.get('Parameter').get('Value') # Retorna o valor do parâmetro
147
+ # Retorna None se o parâmetro não existir no SSM
148
+ return None
149
+
150
+ # Estrutura da resposta: {"Parameter": {"Value": "..."}}
151
+ return response.get("Parameter", {}).get("Value")
42
152
 
43
153
  def get_header(self) -> Header:
44
154
  """
45
- Retorna os parâmetros padrão contidos no header da requisição.
155
+ Extrai e retorna um objeto Header com os principais campos do runtime.
46
156
 
47
157
  Returns:
48
- Header: Objeto Header preenchido com os valores dos headers customizados.
158
+ Header: dataclass/objeto com os campos interpretados do header.
49
159
  """
50
- ctx = self.mcp.get_context() # Obtém o contexto da requisição atual
51
- headers = ctx.request_context.request.headers # Acessa os headers da requisição
52
- # Preenche o objeto Header com os valores dos headers customizados
53
160
  return Header(
54
- current_host=headers.get(f"{self.HEADER_PREFIX}-current-host", None),
55
- user_email=headers.get(f"{self.HEADER_PREFIX}-user-email", None),
56
- jwt_token=headers.get(f"{self.HEADER_PREFIX}-jwt-token", None),
57
- jsessionid=headers.get(f"{self.HEADER_PREFIX}-jsessionid", None),
58
- organization_id=int(headers.get(f"{self.HEADER_PREFIX}-organization-id", 0)),
59
- codparc=int(headers.get(f"{self.HEADER_PREFIX}-codparc", 0)),
60
- iam_user_id=int(headers.get(f"{self.HEADER_PREFIX}-iam-user-id", 0)),
61
- gateway_token=headers.get(f"{self.HEADER_PREFIX}-gateway-token", None)
161
+ # Strings (podem ser None)
162
+ current_host=self._h("current-host"),
163
+ user_email=self._h("user-email"),
164
+ jwt_token=self._h("jwt-token"),
165
+ jsessionid=self._h("jsessionid"),
166
+
167
+ # Inteiros (com fallback seguro para 0)
168
+ organization_id=self._to_int(self._h("organization-id"), 0),
169
+ codparc=self._to_int(self._h("codparc"), 0),
170
+ iam_user_id=self._to_int(self._h("iam-user-id"), 0),
171
+
172
+ # String (pode ser None)
173
+ gateway_token=self._h("gateway-token"),
62
174
  )
63
-
175
+
64
176
  def get_parameter(self, parameter_name: str) -> str:
65
177
  """
66
- Retorna o valor do parâmetro, buscando primeiro na variável de ambiente
67
- e depois no AWS SSM Parameter Store caso não exista na variável de ambiente.
178
+ Recupera um parâmetro sensível/configurável.
179
+
180
+ Ordem de resolução:
181
+ 1) Variáveis de ambiente (ideal para execução local / CI)
182
+ 2) AWS SSM Parameter Store (ideal para produção via cofre)
183
+
184
+ Observação:
185
+ - Implementação evita avaliar SSM antecipadamente.
186
+ (Não usamos mais os.getenv(name, default_func()) porque chamaria AWS sempre.)
187
+
188
+ Args:
189
+ parameter_name: Nome do parâmetro.
190
+
191
+ Returns:
192
+ str | None: valor encontrado ou None.
193
+ """
194
+ value = self._get_from_env(parameter_name)
195
+ if value is not None:
196
+ return value
197
+ return self._get_from_stores(parameter_name)
198
+
199
+ def _get_from_env(self, parameter_name: str):
200
+ """
201
+ Provider interno: busca em variáveis de ambiente do sistema.
202
+
203
+ Args:
204
+ parameter_name: Nome do parâmetro.
205
+
206
+ Returns:
207
+ str | None
208
+ """
209
+ return os.getenv(parameter_name)
210
+
211
+ def _get_from_stores(self, parameter_name: str):
212
+ """
213
+ Provider interno: busca em fontes externas (hoje apenas SSM).
214
+
215
+ Este método existe para facilitar manutenção e evolução:
216
+ amanhã pode incluir outros provedores (Secrets Manager, Vault, etc.)
217
+ sem mudar a API pública de get_parameter().
68
218
 
69
219
  Args:
70
- parameter_name (str): Nome do parâmetro a ser buscado.
220
+ parameter_name: Nome do parâmetro.
71
221
 
72
222
  Returns:
73
- str: Valor do parâmetro, ou None se não encontrado.
223
+ str | None
74
224
  """
75
- # Busca o valor na variável de ambiente, se não existir busca no SSM
76
- return os.getenv(
77
- parameter_name,
78
- self.__get_from_ssm(parameter_name)
79
- )
225
+ return self.__get_from_ssm(parameter_name)
226
+
227
+
228
+ __all__ = ["BiaUtil"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: biatoolkit
3
- Version: 1.0.3
3
+ Version: 1.1.0
4
4
  Summary: Biblioteca para desenvolvedores que utilizam o BiaAgentBuilder
5
5
  Author: Bia Platform Team
6
6
  Author-email: data.platform@sankhya.com.br
@@ -19,45 +19,73 @@ Dynamic: summary
19
19
 
20
20
  # Bia Toolkit
21
21
 
22
- Biblioteca Python para facilitar o desenvolvimento de servidores MCP integrados ao Bia Agent Builder.
22
+ Biblioteca Python para facilitar o desenvolvimento de servidores MCP integrados ao **Bia Agent Builder**.
23
23
 
24
- ## **Principais classes da biblioteca**
24
+ O objetivo da Bia Toolkit é abstrair detalhes técnicos do MCP (Model Context Protocol),
25
+ fornecendo utilitários prontos para:
26
+ - Comunicação com servidores MCP
27
+ - Leitura de contexto do runtime (headers)
28
+ - Recuperação segura de parâmetros e segredos
25
29
 
26
- Nesta seção você encontrará uma breve descrição de cada classe da biblioteca **Bia Toolkit**.
30
+ ---
27
31
 
28
- ### **BasicClient**
32
+ ## Principais classes da biblioteca
29
33
 
30
- A classe `BasicClient` tem o objetivo de criar um cliente HTTP para comunicação com servidores MCP (Model Context Protocol).
34
+ ### BiaClient
31
35
 
32
- **Principais métodos**:
36
+ A classe `BiaClient` encapsula um cliente HTTP assíncrono para comunicação com servidores MCP
37
+ (Model Context Protocol).
33
38
 
34
- - **list_tools**: Lista todas as ferramentas disponíveis no servidor MCP.
35
- - **call_tool**: Executa uma ferramenta específica no servidor MCP.
39
+ Ela esconde toda a complexidade de:
40
+ - Conexão HTTP streamable
41
+ - Inicialização de sessões MCP
42
+ - Execução de tools
36
43
 
37
- ### **Util**
44
+ #### Principais métodos
38
45
 
39
- A classe `Util` fornece métodos auxiliares para gerenciar headers de requisições e parâmetros de configuração em servidores MCP.
46
+ - **list_tools()**
47
+ - Lista todas as ferramentas disponíveis no servidor MCP.
40
48
 
41
- **Principais métodos**:
49
+ - **call_tool(tool_name, params=None)**
50
+ - Executa uma ferramenta específica disponível no servidor MCP.
42
51
 
43
- - **construtor**: Recebe uma instância de FastMCP para acessar o contexto das requisições. Armazena a referência do MCP para uso nos métodos.
52
+ ---
44
53
 
45
- - **__get_from_ssm**: Busca um parâmetro no AWS SSM Parameter Store.
54
+ ### BiaUtil
46
55
 
47
- - **get_header**: Extrai e retorna todos os headers customizados da requisição atual. Retorna um objeto Header com os seguintes campos:
48
- - current_host: Host do ERP no qual o copilot está em execução.
49
- - user_email: Email do usuário autenticado.
50
- - jwt_token: Token JWT do usuário -> SankhyaID, SankhyaPass ou Token interno Bia.
51
- - jsessionid: ID de autenticação do ERP.
52
- - organization_id: ID da organização da Bia.
53
- - codparc: Código do parceiro (parceiro Sankhya).
54
- - iam_user_id: ID do usuário do BIA IAM.
55
- - gateway_token: Token primário do Sankhya API Gateway.
56
+ A classe `BiaUtil` fornece métodos auxiliares para uso **dentro de MCP Servers**,
57
+ permitindo acesso fácil a:
58
+ - Headers padronizados enviados pelo runtime do Bia Agent Builder
59
+ - Parâmetros sensíveis vindos de variáveis de ambiente ou cofre de segredos (AWS SSM)
60
+
61
+ #### Principais métodos
62
+
63
+ - **construtor**
64
+ - Recebe uma instância de `FastMCP` para acessar o contexto da requisição atual.
65
+
66
+ - **get_header()**
67
+ - Extrai e retorna os headers customizados do runtime.
68
+ - Retorna um objeto `Header` com os campos:
69
+ - `current_host`: Host do ERP no qual o copilot está em execução.
70
+ - `user_email`: Email do usuário autenticado.
71
+ - `jwt_token`: Token JWT do usuário.
72
+ - `jsessionid`: ID de autenticação do ERP.
73
+ - `organization_id`: ID da organização da Bia.
74
+ - `codparc`: Código do parceiro Sankhya.
75
+ - `iam_user_id`: ID do usuário do BIA IAM.
76
+ - `gateway_token`: Token primário do Sankhya API Gateway.
77
+
78
+ - **get_parameter(parameter_name)**
79
+ - Recupera parâmetros sensíveis seguindo a ordem:
80
+ 1. Variáveis de ambiente do sistema
81
+ 2. AWS SSM Parameter Store (fallback)
82
+
83
+ **Observações importantes:**
84
+ - O SSM só é consultado se o parâmetro **não existir** nas variáveis de ambiente.
85
+ - Em produção, a busca no SSM depende do header
86
+ `X-Amzn-Bedrock-AgentCore-Runtime-Custom-prefix`.
87
+ - Se esse header não estiver presente, o método retorna `None`.
56
88
 
57
- - **get_parameter**: Busca o parâmetro informado em duas fontes distintas:
58
- - Primeiro: Variáveis de ambiente do sistema.
59
- - Segundo: AWS SSM Parameter Store (se não encontrado nas variáveis de ambiente).
60
- - Retorna o valor do parâmetro ou None se não encontrado em nenhuma fonte.
61
89
 
62
90
  ## **Como utilizar**
63
91
 
@@ -97,7 +125,6 @@ def adicionar(id: int, nome: str) -> str:
97
125
  novo_item = {"id": id, "nome": nome}
98
126
  return json.dumps(novo_item, indent=4, sort_keys=True)
99
127
 
100
-
101
128
  if __name__ == "__main__":
102
129
  mcp.run(transport="streamable-http")
103
130
  ```
@@ -128,32 +155,29 @@ Crie um novo arquivo chamado `local.py` com o seguinte conteúdo:
128
155
 
129
156
  ```python
130
157
  import asyncio
131
- from biatoolkit.basic_client import BasicClient
158
+ from biatoolkit.basic_client import BiaClient
132
159
 
133
160
  MCP_SERVER_URL = "http://0.0.0.0:8000/mcp"
134
- client = BasicClient(MCP_SERVER_URL)
161
+ client = BiaClient(MCP_SERVER_URL)
135
162
 
136
- async def list_tools() -> None:
163
+ async def list_tools():
137
164
  tools = await client.list_tools()
138
165
  for tool in tools.tools:
139
166
  print(f"Tool: {tool.name}, Description: {tool.description}")
140
167
 
141
-
142
- async def call_tool(tool_name: str, params: dict = None) -> None:
168
+ async def call_tool(tool_name: str, params: dict = None):
143
169
  result = await client.call_tool(tool_name, params)
144
170
  print(result.content[0].text)
145
171
 
146
-
147
172
  async def main():
148
173
  await list_tools()
149
-
150
174
 
151
175
  asyncio.run(main())
152
176
  ```
153
177
 
154
178
  #### **Entendendo o código**
155
179
 
156
- - **BasicClient**: É uma classe da biblioteca **Bia Toolkit** que encapsula um cliente HTTP para comunicação com servidores MCP.
180
+ - **BiaClient**: É uma classe da biblioteca **Bia Toolkit** que encapsula um cliente HTTP para comunicação com servidores MCP.
157
181
  - **list_tools**: Executa a instrução `client.list_tools()` para recuperar todas as ferramentas disponíveis no servidor MCP.
158
182
  - **call_tool**: Executa a instrução `client.call_tool(tool_name, params)` para executar uma ferramenta específica do servidor MCP.
159
183
 
@@ -204,7 +228,7 @@ Se seu servidor MCP estiver sendo executado **localmente**, você conseguirá in
204
228
 
205
229
  ```python
206
230
  import asyncio
207
- from biatoolkit.basic_client import BasicClient
231
+ from biatoolkit.basic_client import BiaClient
208
232
 
209
233
  MCP_SERVER_URL = "http://0.0.0.0:8000/mcp"
210
234
 
@@ -226,7 +250,7 @@ headers = {
226
250
  "Content-Type": "application/json"
227
251
  }
228
252
 
229
- client = BasicClient(MCP_SERVER_URL, headers=headers)
253
+ client = BiaClient(MCP_SERVER_URL, headers=headers)
230
254
 
231
255
  async def list_tools() -> None:
232
256
  tools = await client.list_tools()
@@ -246,19 +270,13 @@ async def main():
246
270
  asyncio.run(main())
247
271
  ```
248
272
 
249
- #### **Entendendo o código**
250
-
251
- - **headers**: Veja que a variável `headers` é definida com a lista de parâmetros válidos e depois utilizada em `client = BasicClient(MCP_SERVER_URL, headers=headers)`.
252
-
253
- ⚠️ IMPORTANTE: Ao utilizar os serviços de interação com a Bia (**/agent/stream**, **/agent/message** ou **/agent/invoke**), os parâmetros já são automaticamente preenchidos e enviados pelos serviços.
254
-
255
- ### **Recuperando os parâmetros no MCP Server enviados via header**
273
+ ...existing code...
256
274
 
257
- Para recuperar os parâmetros no MCP Server que foram enviados por meio do `header` da requisição, basta utilizar a classe `Util` conforme a seguir:
275
+ Para recuperar os parâmetros no MCP Server que foram enviados por meio do `header` da requisição, basta utilizar a classe `BiaUtil` conforme a seguir:
258
276
 
259
277
  ```python
260
278
  from mcp.server.fastmcp import FastMCP
261
- from biatoolkit.util import Util
279
+ from biatoolkit.util import BiaUtil
262
280
 
263
281
  mcp = FastMCP(host="0.0.0.0", stateless_http=True)
264
282
 
@@ -266,7 +284,7 @@ mcp = FastMCP(host="0.0.0.0", stateless_http=True)
266
284
  def processar() -> str:
267
285
  """Executa o processamento de algo"""
268
286
 
269
- util = Util(mcp)
287
+ util = BiaUtil(mcp)
270
288
  header = util.get_header()
271
289
 
272
290
  # Exemplo de uso dos parâmetros do header. Utilize conforme a necessidade
@@ -296,11 +314,11 @@ Você pode utilizar parâmetros sensíveis de duas formas:
296
314
  - Usando o cofre de segredos do Bia Agent Builder para execução em ambiente produtivo.
297
315
  - Você pode adicionar parâmetros sensíveis no cofre de segredos do Bia Agent Builder. Para adicionar, alterar e excluir os parâmetros do cofre, utilize as funcionalidades da Plataforma Bia Agent Builder UI.
298
316
 
299
- Para recuperar um valor sensível no seu MCP Server, utilize o método `get_parameter(parameter_name: str)` da classe `Util`.
317
+ Para recuperar um valor sensível no seu MCP Server, utilize o método `get_parameter(parameter_name: str)` da classe `BiaUtil`.
300
318
 
301
319
  ```python
302
320
  from mcp.server.fastmcp import FastMCP
303
- from biatoolkit.util import Util
321
+ from biatoolkit.util import BiaUtil
304
322
 
305
323
  mcp = FastMCP(host="0.0.0.0", stateless_http=True)
306
324
 
@@ -308,7 +326,7 @@ mcp = FastMCP(host="0.0.0.0", stateless_http=True)
308
326
  def processar() -> str:
309
327
  """Executa o processamento de algo"""
310
328
 
311
- util = Util(mcp)
329
+ util = BiaUtil(mcp)
312
330
  valor = util.get_parameter("meu_parametro")
313
331
 
314
332
  # Exemplo de uso do parâmetro recuperado. Utilize conforme a necessidade
@@ -0,0 +1,10 @@
1
+ biatoolkit/__init__.py,sha256=OStl3T8OY7YdGdpKIpwXtTo-IjcQxzDRHzpAoBEM8yU,98
2
+ biatoolkit/basic_client.py,sha256=qp5T85wm6D80i3Owjz9AxUYKmaKHgImxirYCduBi1gk,4760
3
+ biatoolkit/settings.py,sha256=gA07EMEb9k5tt6ySCOYTV4pKHPSiG7nSap2qhHQhmFY,3494
4
+ biatoolkit/util.py,sha256=PgYKRl85K4wmF4WFrabTQ3yiTmgw9S2BxZ-uvwFnP6A,7768
5
+ biatoolkit/schema/__init__.py,sha256=6lvcENhbQnelI2faBGnEs0yG0k4SkwtIrtmn4PtKWvg,32
6
+ biatoolkit/schema/header.py,sha256=COJPlqK1cFvvWzDcCw2ru1jszWPgyyvabkjzDCc8AjM,683
7
+ biatoolkit-1.1.0.dist-info/METADATA,sha256=4_YWz1I9WXRO91QaQkmydpr6DpeZh_bNBkhqsFedQNo,13174
8
+ biatoolkit-1.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
9
+ biatoolkit-1.1.0.dist-info/top_level.txt,sha256=DyrMS0X6u1FDA9uT854LxoT3X7gzMAlsFQabE-WuKMc,11
10
+ biatoolkit-1.1.0.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- biatoolkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- biatoolkit/basic_client.py,sha256=_N2-NcrVWfm-rUuJUksOdR8GONmLYzooMhX1El49A3c,2581
3
- biatoolkit/util.py,sha256=wP1r29MLVk27iMnMG_Xywa6Yt6H-XfHdlrb4u8Tmg6c,3288
4
- biatoolkit/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- biatoolkit/schema/header.py,sha256=COJPlqK1cFvvWzDcCw2ru1jszWPgyyvabkjzDCc8AjM,683
6
- biatoolkit-1.0.3.dist-info/METADATA,sha256=3kUZGId145VtBiInuRnFqwdy9sJMEqbKqAHUAGYB0BA,13181
7
- biatoolkit-1.0.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
8
- biatoolkit-1.0.3.dist-info/top_level.txt,sha256=DyrMS0X6u1FDA9uT854LxoT3X7gzMAlsFQabE-WuKMc,11
9
- biatoolkit-1.0.3.dist-info/RECORD,,