Criando um Agente de IA Local e Personalizado com Google ADK, sem e com MCP

16/07/2025
21 min
Programação, Publicações Ligo
16 curtidas
Ouvir
Navegue por Tópicos
Compartilhe
  • Comentar
Ouvir

Neste guia detalhado, você aprenderá a configurar um agente inteligente local utilizando o Google Agent Development Kit (ADK) sem e com servidor Model Context Protocol (MCP). Esta abordagem é ideal para projetos que exigem privacidade, controle total e flexibilidade, especialmente em cenários sensíveis ou operações offline. A grande vantagem de um agente local é que ele permite o desenvolvimento e a execução de funcionalidades de IA no seu próprio ambiente, sem depender de serviços em nuvem externos, garantindo assim maior autonomia e segurança de dados.

Componentes Chave:

1. Google ADK (Agent Development Kit):

    ◦ O ADK é um framework robusto da Google projetado para facilitar a criação de agentes inteligentes.

    ◦ Ele oferece suporte nativo a ferramentas personalizadas e capacidades de orquestração, permitindo a construção de arquiteturas de agente modulares e escaláveis.

    ◦ O ADK suporta diversas formas de interação, incluindo HTTP, Server-Sent Events (SSE) e até mesmo comunicação via processos stdio. Para mais detalhes, você pode consultar a documentação oficial.

2. MCP (Model Context Protocol) – Opcional:

    ◦ O Model Context Protocol é uma forma padronizada e organizada de estruturar as informações que são enviadas para Modelos de Linguagem (LLMs).

    ◦ Seu objetivo é otimizar a comunicação com LLMs, tornando-a mais eficiente e consistente.

    ◦ É importante notar que, embora o MCP possa ser utilizado, a criação do agente local com o Google

ADK pode ser feita com ou sem um servidor MCP.

Guia de Implementação:

1. Instalando as Dependências:

Para começar, você precisará instalar as bibliotecas necessárias. Escolha o gerenciador de pacotes de sua preferência:

    ◦ Usando pip: 

pip install google-adk litellm

    ◦ Usando uv (alternativa mais rápida):

pip install uv
uv init
uv add google-adk litellm

Estas ferramentas são essenciais para o desenvolvimento com Google ADK, sendo o litellm crucial para a integração com modelos de linguagem locais.

2. Criando a Estrutura Básica do Agente:

O Google ADK simplifica o início de novos projetos, fornecendo um comando para gerar uma estrutura de arquivos básicos, eliminando a necessidade de começar do zero. No seu ambiente onde o google-adk foi instalado, execute:

adk create primeiro_agente

Este comando cria automaticamente a estrutura de diretórios e arquivos fundamentais para o seu agente.

3. Configurando o Modelo Local e Importações:

Para utilizar um modelo de linguagem local, é necessário importar as classes Agent e LiteLlm do Google ADK. A classe LiteLlm é a ponte para a integração com modelos locais:

from google.adk.agents import Agent
from google.adk.models.lite_llm import LiteLlm

O LiteLlm permite que você especifique o modelo local a ser usado, como um servidor Ollama configurado na sua máquina.

4. Desenvolvendo uma Ferramenta Personalizada:

Agentes inteligentes frequentemente precisam interagir com o mundo exterior para coletar informações ou executar ações. No Google ADK, isso é feito através de ferramentas (tools). Vamos criar uma ferramenta simples para obter a hora atual:

from datetime import datetime
from typing import Final

def pegar_horas() -> dict:
    """
    Ferramenta: Obter a hora atual.
    Descrição:
    Retorna a hora atual do sistema no formato "HH:MM:SS".
    Parâmetros:
    - Nenhum
    Retorna:
    - Um dicionário com a hora atual.
    """
    agora: Final[datetime] = datetime.now()
    hora_formatada: str = agora.strftime("%H:%M:%S")
    return {"text": hora_formatada}

Pontos Cruciais para Ferramentas:

    ◦ Documentação Clara: É fundamental que a função esteja muito bem documentada (usando docstrings). Essa documentação é o que permite ao agente saber como e por que usar a ferramenta, interpretando sua finalidade e seus parâmetros.

    ◦ Retorno de Dicionário: A função deve retornar um dicionário (dict), pois este é o padrão esperado pelo Google ADK para processar as saídas das ferramentas.

5. Construindo o Primeiro Agente:

Finalmente, iremos instanciar nosso agente principal, configurando seu modelo, nome, descrição, instruções e as ferramentas que ele pode utilizar:

ollama_endpoint = "http://localhost:11434"
root_agent = Agent(
    model=LiteLlm(model="ollama_chat/qwen2.5:14b", base_url=ollama_endpoint),
    name='root_agent',
    description='Você é um assistente que responde perguntas.',
    instruction='''Você é um agente inteligente.
    Ferramentas:
    pegar_horas()
    Retorna a hora atual do sistema.
    ''',
    tools=[pegar_horas]
)

Detalhes Importantes da Configuração do Agente:

    ◦ model: Este parâmetro utiliza a classe LiteLlm para configurar o modelo de linguagem local.

        ▪ model=”ollama_chat/qwen2.5:14b”: Define o nome do modelo específico que o agente utilizará. Você pode alterar este valor conforme o modelo local que você tiver disponível.

        ▪ base_url=ollama_endpoint: Aponta para o endereço do seu servidor de modelo local (neste exemplo, um servidor Ollama rodando na porta 11434).

    ◦ name e description: Atribuem um nome e uma breve descrição ao agente, auxiliando na sua identificação.

    ◦ instruction: Fornece as diretrizes e o comportamento esperado do agente. É aqui que você também lista as ferramentas disponíveis, descrevendo brevemente suas funcionalidades para que o agente possa decidir quando usá-las.

    ◦ tools: Uma lista das funções (ferramentas) que o agente pode chamar. É crucial que as funções adicionadas aqui estejam corretamente documentadas para que o Google ADK as reconheça.

Após configurar o agente, o Google ADK oferece uma interface web intuitiva para testá-lo e interagir:

No terminal, navegue até o diretório do seu projeto e digite:

adk web

Este comando iniciará o servidor web do ADK.

Abra seu navegador e acesse o endereço:

http://localhost:8000

Você verá a interface do Google ADK.

Selecione o agente que você acabou de criar e comece a interagir com ele.

Comportamento Inteligente do Agente:

Observe que, mesmo em interações iniciais onde uma ferramenta pode não ser necessária, o agente é capaz de discernir quando e como utilizar a ferramenta criada para fornecer a resposta mais adequada ao usuário. Por exemplo, ao perguntar “Que horas são?”, o agente identificará a necessidade de usar a função pegar_horas() para responder.

6. Entendendo o MCP (Model Context Protocol)

Antes de mergulhar na implementação, é útil reforçar o papel do MCP. Ele é uma forma padronizada e organizada de estruturar as informações enviadas para Modelos de Linguagem (LLMs), visando otimizar a comunicação com LLMs, tornando-a mais eficiente e consistente. Embora seja opcional, ele permite uma abordagem mais robusta para o gerenciamento de ferramentas.

7. Criando o Servidor MCP (Etapas e Componentes Chave)

A seção do seu artigo pode detalhar as seguintes etapas para criar o servidor MCP:

Importando as Bibliotecas Necessárias:

import asyncio
import json
import mcp.server.stdio 
from google.adk.tools.function_tool import FunctionTool
from google.adk.tools.mcp_tool.conversion_utils import adk_to_mcp_tool_type
from mcp import types as mcp_types
from mcp.server.lowlevel import NotificationOptions, Server
from mcp.server.models import InitializationOptions

    ◦ Para começar a construir o servidor MCP, é fundamental importar um conjunto específico de bibliotecas. Isso inclui asyncio e json para operações gerais, além de módulos específicos do MCP (mcp.server.stdio, mcp.types, mcp.server.lowlevel, mcp.server.models) e do Google ADK para ferramentas (google.adk.tools.function_tool, google.adk.tools.mcp_tool.conversion_utils, google.adk.tools.mcp_tool.mcp_session_manager).

    ◦ Um ponto importante a destacar é a função adk_to_mcp_tool_type, que é uma funcionalidade nativa do Google ADK para converter funções Python diretamente para o protocolo de comunicação necessário para o MCP.

Definindo as Ferramentas para o MCP Server:

from datetime import datetime
from typing import Final

def pegar_horas() -> dict:
    """
    Ferramenta: Obter a hora atual.
    Descrição:
    Retorna a hora atual do sistema no formato "HH:MM:SS".
    Parâmetros:
    - Nenhum
    Retorna:
    - Um dicionário com a hora atual.
    """
    agora: Final[datetime] = datetime.now()
    hora_formatada: str = agora.strftime("%H:%M:%S")
    return {"text": hora_formatada}
# --- MCP Server Setup ---
app = Server("mcp-server")
# Coloque todas as ferramentas
ADK_DB_TOOLS = {
    "pegar_horas": FunctionTool(func=pegar_horas)
}

    ◦ A fonte demonstra a reutilização da ferramenta pegar_horas() (obter a hora atual). Essa ferramenta, assim como outras que você possa criar, será exposta pelo servidor MCP.

    ◦ As ferramentas são armazenadas em um dicionário, ADK_DB_TOOLS, onde a chave é o nome da ferramenta e o valor é uma instância de FunctionTool do Google ADK, que encapsula a função Python. Exemplo: ADK_DB_TOOLS = {“pegar_horas”: FunctionTool(func=pegar_horas)}.

Implementando as Funções Essenciais do Servidor MCP:

@app.list_tools() 
async def list_mcp_tools() -> list[mcp_types.Tool]:
    """MCP handler to list tools this server exposes."""
    mcp_tools_list = []
    for tool_name, adk_tool_instance in ADK_DB_TOOLS.items():
        if not adk_tool_instance.name:
            adk_tool_instance.name = tool_name
        mcp_tool_schema = adk_to_mcp_tool_type(adk_tool_instance)
        mcp_tools_list.append(mcp_tool_schema)
    return mcp_tools_list

@app.call_tool()
async def call_mcp_tool(name: str, arguments: dict) -> list[mcp_types.TextContent]:
    """MCP handler to execute a tool call requested by an MCP client."""
    if name in ADK_DB_TOOLS:
        adk_tool_instance = ADK_DB_TOOLS[name]
        try:
            adk_tool_response = await adk_tool_instance.run_async(
                args=arguments,
                tool_context=None,  # type: ignore
            )
            response_text = json.dumps(adk_tool_response, indent=2)
            return [mcp_types.TextContent(type="text", text=response_text)]
        except Exception as e:
            error_payload = {
                "success": False,
                "message": f"Failed to execute tool '{name}': {str(e)}",
            }
            error_text = json.dumps(error_payload)
            return [mcp_types.TextContent(type="text", text=error_text)]
    else:
        error_payload = {
            "success": False,
            "message": f"Tool '{name}' not implemented by this server.",
        }
        error_text = json.dumps(error_payload)
        return [mcp_types.TextContent(type="text", text=error_text)]

    ◦ Dois métodos são obrigatórios no servidor MCP para que ele possa listar e chamar ferramentas: list_mcp_tools e call_mcp_tool.

    ◦ @app.list_tools() async def list_mcp_tools() -> list[mcp_types.Tool]::

        ▪ Esta função é responsável por listar todas as ferramentas que o servidor MCP expõe.

        ▪ Ela itera sobre as ferramentas definidas em ADK_DB_TOOLS e utiliza adk_to_mcp_tool_type para converter cada instância de ferramenta do ADK para o formato de esquema de ferramenta que o MCP espera.

    ◦ @app.call_tool() async def call_mcp_tool(name: str, arguments: dict) -> list[mcp_types.TextContent]::

        ▪ Esta função é o manipulador do MCP para executar uma chamada de ferramenta solicitada por um cliente MCP.

        ▪ Ela verifica se o nome da ferramenta solicitado (name) existe em ADK_DB_TOOLS.

        ▪ Se a ferramenta existir, ela executa a função associada (adk_tool_instance.run_async) e retorna a resposta formatada como mcp_types.TextContent.

        ▪ É crucial que o código inclua o tratamento de erros, retornando uma mensagem clara se a execução da ferramenta falhar ou se a ferramenta não for implementada pelo servidor

8. Executando o Servidor MCP:

# --- MCP Server Runner ---
async def run_mcp_stdio_server():
    """Runs the MCP server, listening for connections over standard input/output."""
    async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
        await app.run(
            read_stream,
            write_stream,
            InitializationOptions(
                server_name=app.name,
                server_version="0.1.0",
                capabilities=app.get_capabilities(
                    notification_options=NotificationOptions(),
                    experimental_capabilities={},
                ),
            ),
        )
if __name__ == "__main__":
    asyncio.run(run_mcp_stdio_server())

    ◦ A função run_mcp_stdio_server() é responsável por iniciar o servidor MCP, ouvindo conexões via entrada/saída padrão (stdio).

    ◦ Ela utiliza mcp.server.stdio.stdio_server() para gerenciar os streams de leitura e escrita.

    ◦ A inicialização do servidor app.run inclui a configuração do server_name, server_version e capabilities.

    ◦ Finalmente, o if __name__ == “__main__”: asyncio.run(run_mcp_stdio_server()) garante que o servidor seja iniciado quando o script Python for executado.

    ◦ Para subir o servidor, basta executar o arquivo Python no terminal. A fonte indica que o servidor estará ativo na porta 3333.

9. Criando o Agente para Comunicar com o Servidor MCP

Uma vez que o servidor MCP esteja ativo e expondo as ferramentas, a configuração do agente do Google ADK muda para apontar para este servidor:

Importações para o Agente MCP:

from google.adk.agents import Agent
from google.adk.models.lite_llm import LiteLlm
from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset
from google.adk.tools.mcp_tool.mcp_session_manager import SseServerParams

    ◦ Você precisará importar MCPToolset e SseServerParams do Google ADK.

Configurando o Agente com o Servidor MCP:

tools = MCPToolset(connection_params=SseServerParams(
        url="http://localhost:3333/sse",
    )
)
ollama_endpoint = "http://localhost:11434"
root_agent = Agent(
    name='agente_com_mcp',
    model=LiteLlm(model="ollama_chat/qwen2.5:14b",base_url=ollama_endpoint),
    description='Agent for tools',
    instruction="""Você é um agente inteligente com acesso a um servidor MCP com ferramentas. Use as ferramentas somente quando necessário para responder com precisão.""",
    tools=[tools]
)

    ◦ Em vez de listar as ferramentas diretamente no construtor do Agent, você agora indica o servidor MCP de ferramentas ao agente.

    ◦ Isso é feito instanciando MCPToolset e passando os parâmetros de conexão (connection_params) que incluem a URL do servidor MCP (SseServerParams(url=”http://localhost:3333/sse”)).

    ◦ A instância de MCPToolset (por exemplo, tools = MCPToolset(…)) é então passada para o parâmetro tools do Agent.

    ◦ A configuração do modelo local (LiteLlm) e o ollama_endpoint permanecem os mesmos.

    ◦ A instruction do agente também muda; agora ela deve indicar que o agente tem acesso a um servidor MCP com ferramentas, e que deve usá-las quando necessário.

Vantagem Crucial:

    ◦ Um detalhe importante para destacar é que, com o servidor MCP, você não precisa mais descrever as ferramentas existentes no instruction (prompt) do agente, pois o servidor MCP as comunica diretamente ao agente. Isso simplifica a manutenção do agente e a adição de novas ferramentas.

10. Testando o Agente com MCP:

Com o servidor MCP ativo:

    ◦ Você executa em outro terminal o comando adk web dentro do diretório do seu projeto.

    ◦ Em seguida, acessa http://localhost:8000 no navegador.

Note que agora você pode perguntar ao agente quais as ferramentas existem no servidor dele sem ter que especificar no prompt de comando.

11. Interagindo com o Agente via API HTTP

O Google ADK oferece diversas maneiras de interagir com o agente que você criou. Além da flexibilidade de configurar agentes localmente para privacidade e controle total, ele também permite a interação programática através de uma API HTTP. Isso é crucial para integrar seu agente a outras aplicações, sistemas ou para realizar testes automatizados.

Com o servidor web do ADK ativo (http://localhost:8000), você pode enviar requisições HTTP POST para interagir com o agente de forma programática.

Endpoint da API: As interações com o agente são realizadas através do endpoint /run do servidor web do ADK.

POST http://localhost:8000/run

Corpo da Requisição (Formato JSON): A requisição deve incluir um corpo JSON estruturado com as informações necessárias para a interação com o agente. É importante que este corpo esteja corretamente formatado:

{
	"appName": "agente_com_mcp",
	"userId": "1",
	"sessionId": "1",
	"newMessage": {
		"parts": [{
			"text": "oi tudo bem"
		}],
		"role": "user"
	},
	"streaming": false
}

    ◦ “appName”: Este campo é crucial e deve corresponder exatamente ao name que você atribuiu ao seu agente durante a configuração. Por exemplo, para o agente configurado com MCP, o nome utilizado foi ‘agente_com_mcp’, e para o primeiro agente sem MCP, foi ‘root_agent’.

    ◦ “userId”: Um identificador para o usuário que está interagindo. Pode ser usado para distinguir conversas de diferentes usuários.

    ◦ “sessionId”: Um identificador para a sessão de conversa. O agente usa este ID para manter o contexto de uma conversa ao longo de várias interações.

    ◦ “newMessage”: Contém a mensagem atual do usuário que será enviada ao agente.

        ▪ “parts”: Uma lista de partes da mensagem. Atualmente, a parte textual é a mais comum.

        ▪ “text”: O conteúdo textual da sua mensagem.

        ▪ “role”: O papel do remetente da mensagem. Para mensagens do usuário, o valor é “user”.

    ◦ “streaming”: Um valor booleano (true ou false) que indica se a resposta do agente deve ser transmitida em tempo real (streaming) ou entregue de uma vez após a conclusão. Para este exemplo, false indica que a resposta será completa.

Exemplo de Uso:

curl -X POST http://localhost:8000/run  
-d '{"appName": "agente_com_mcp","userId": "1","sessionId": "1","newMessage": {"parts": [{"text": "qual as horas?"}],"role": "user"},"streaming": False}'

12. Acesso ao Swagger

Para acessar o Swagger vá no endereço:

http://localhost:8000/docs

Referências:


https://google.github.io/adk-docs/
https://modelcontextprotocol.io/introduction
https://ollama.com/
https://google.github.io/adk-docs/tools/mcp-tools/
https://medium.com/@ssupinma/implementing-google-adk-and-mcp-on-windows-a-practical-guide-e27e78d1b165
https://medium.com/hostspaceng/building-ai-agents-with-google-adk-fastapi-and-mcp-031447925896

Navegue por Tópicos
Compartilhe
  • Comentar
Este post não tem tags.

Adriano Pericles

Comentários mais recentes

  • Vitor Ohnesorg
    Postado em 06/12/2025

    Excelmente artigo. Parabéns.

Gostou? Deixe seu comentário aqui...

Acessar o conteúdo