
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 litellmEstas 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_agenteEste 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 LiteLlmO 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 webEste 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:

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
Excelmente artigo. Parabéns.