

Como o MCP está mudando a forma como agentes de IA se conectam a ferramentas externas e sistemas legados. Implementação prática com Python e TypeScript.
O Model Context Protocol (MCP) é uma especificação aberta criada pela Anthropic que está rapidamente se tornando o padrão para conectar LLMs a ferramentas externas. Neste artigo, explico o que é, por que importa e como implementar.
Antes do MCP, cada integração de agente era um projeto customizado:
O resultado era fragmentação: ferramentas escritas para um framework não funcionavam em outro. O MCP resolve isso com um protocolo padronizado.
O MCP usa uma arquitetura cliente-servidor:
┌─────────────────┐ MCP Protocol ┌─────────────────┐
│ MCP Client │◄────────────────────►│ MCP Server │
│ (Claude, etc.) │ │ (Suas Tools) │
└─────────────────┘ └─────────────────┘
┌─────────────────┐ MCP Protocol ┌─────────────────┐
│ MCP Client │◄────────────────────►│ MCP Server │
│ (Claude, etc.) │ │ (Suas Tools) │
└─────────────────┘ └─────────────────┘
1. Tools: funções que o LLM pode chamar 2. Resources: dados que o LLM pode ler (arquivos, URLs, banco de dados) 3. Prompts: templates de prompt reutilizáveis
from mcp.server import Server
from mcp.server.models import InitializationOptions
from mcp.types import Tool, TextContent
import mcp.server.stdio
server = Server("meu-servidor-mcp")
@server.list_tools()
async def list_tools() -> list[Tool]:
return [
Tool(
name="buscar_contrato",
description="Busca contratos no banco de dados do Detran-RJ por número ou fornecedor",
inputSchema={
"type": "object",
"properties": {
"numero": {"type": "string", "description": "Número do contrato"},
"fornecedor": {"type": "string", "description": "Nome do fornecedor"},
},
"required": [],
},
),
Tool(
name="analisar_contrato",
description="Analisa um contrato e extrai cláusulas críticas",
inputSchema={
"type": "object",
"properties": {
"contrato_id": {"type": "string", "description": "ID do contrato"},
},
"required": ["contrato_id"],
},
),
]
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
if name == "buscar_contrato":
results = await db.search_contracts(
numero=arguments.get("numero"),
fornecedor=arguments.get("fornecedor"),
)
return [TextContent(type="text", text=format_contracts(results))]
elif name == "analisar_contrato":
contract = await db.get_contract(arguments["contrato_id"])
analysis = await analyze_with_llm(contract)
return [TextContent(type="text", text=analysis)]
raise ValueError(f"Tool desconhecida: {name}")
async def main():
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
InitializationOptions(
server_name="detran-contratos",
server_version="1.0.0",
),
)
from mcp.server import Server
from mcp.server.models import InitializationOptions
from mcp.types import Tool, TextContent
import mcp.server.stdio
server = Server("meu-servidor-mcp")
@server.list_tools()
async def list_tools() -> list[Tool]:
return [
Tool(
name="buscar_contrato",
description="Busca contratos no banco de dados do Detran-RJ por número ou fornecedor",
inputSchema={
"type": "object",
"properties": {
"numero": {"type": "string", "description": "Número do contrato"},
"fornecedor": {"type": "string", "description": "Nome do fornecedor"},
},
"required": [],
},
),
Tool(
name="analisar_contrato",
description="Analisa um contrato e extrai cláusulas críticas",
inputSchema={
"type": "object",
"properties": {
"contrato_id": {"type": "string", "description": "ID do contrato"},
},
"required": ["contrato_id"],
},
),
]
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
if name == "buscar_contrato":
results = await db.search_contracts(
numero=arguments.get("numero"),
fornecedor=arguments.get("fornecedor"),
)
return [TextContent(type="text", text=format_contracts(results))]
elif name == "analisar_contrato":
contract = await db.get_contract(arguments["contrato_id"])
analysis = await analyze_with_llm(contract)
return [TextContent(type="text", text=analysis)]
raise ValueError(f"Tool desconhecida: {name}")
async def main():
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
InitializationOptions(
server_name="detran-contratos",
server_version="1.0.0",
),
)
Para usar seu servidor MCP com Claude Desktop, adicione ao claude_desktop_config.json:
{
"mcpServers": {
"detran-contratos": {
"command": "python",
"args": ["/path/to/server.py"],
"env": {
"DATABASE_URL": "postgresql://...",
"API_KEY": "..."
}
}
}
}
{
"mcpServers": {
"detran-contratos": {
"command": "python",
"args": ["/path/to/server.py"],
"env": {
"DATABASE_URL": "postgresql://...",
"API_KEY": "..."
}
}
}
}
LangChain já tem suporte nativo a MCP:
from langchain_mcp_adapters.tools import load_mcp_tools
from langgraph.prebuilt import create_react_agent
from langchain_anthropic import ChatAnthropic
async def create_agent_with_mcp():
# Carrega tools do servidor MCP
tools = await load_mcp_tools("detran-contratos")
# Cria agente com as tools
model = ChatAnthropic(model="claude-3-5-sonnet-20241022")
agent = create_react_agent(model, tools)
return agent
from langchain_mcp_adapters.tools import load_mcp_tools
from langgraph.prebuilt import create_react_agent
from langchain_anthropic import ChatAnthropic
async def create_agent_with_mcp():
# Carrega tools do servidor MCP
tools = await load_mcp_tools("detran-contratos")
# Cria agente com as tools
model = ChatAnthropic(model="claude-3-5-sonnet-20241022")
agent = create_react_agent(model, tools)
return agent
O MCP está se tornando o "HTTP das ferramentas de IA". Assim como HTTP padronizou a comunicação web, o MCP está padronizando como LLMs se conectam ao mundo.
Já existem servidores MCP para: GitHub, Slack, Google Drive, PostgreSQL, Puppeteer, e dezenas de outros serviços. Isso significa que você pode conectar Claude ou qualquer LLM compatível a qualquer uma dessas ferramentas sem escrever código de integração customizado.
O MCP representa uma mudança de paradigma: de integrações proprietárias para um ecossistema aberto e interoperável. Se você está construindo agentes de IA, vale a pena investir tempo aprendendo MCP agora — ele vai economizar muito tempo de integração no futuro.
Moises Costa é AI Engineer e usa MCP em produção no Detran-RJ. Veja projetos no Hugging Face.