MCP: integrando IA com ferramentas externas
O Model Context Protocol (MCP) é um protocolo aberto que permite a LLMs (Large Language Models) interagirem com ferramentas externas de forma padronizada. Pense como “USB para IA” — qualquer ferramenta que implemente o protocolo funciona com qualquer LLM que o suporte.
O que é MCP?
MCP define um padrão para comunicação entre:
- MCP Client: o LLM ou aplicação que quer usar ferramentas
- MCP Server: o serviço que expõe ferramentas e recursos
┌─────────────┐ MCP ┌─────────────┐
│ LLM/Agent │◄────────────►│ MCP Server │
│ (Client) │ │ (Tools, │
│ │ │ Resources) │
└─────────────┘ └─────────────┘
Por que MCP?
Sem MCP, cada integração IA é custom:
LLM + Slack = código custom
LLM + GitHub = código custom
LLM + Database = código custom
Com MCP:
LLM + Slack MCP Server = funciona
LLM + GitHub MCP Server = funciona
LLM + Database MCP Server = funciona
Implementando um MCP Server em Python
Instalação
pip install mcp
Server básico
# mcp_server.py
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
import json
server = Server("meu-mcp-server")
@server.list_tools()
async def list_tools():
return [
Tool(
name="calcular",
description="Realiza operações matemáticas básicas",
inputSchema={
"type": "object",
"properties": {
"expressao": {
"type": "string",
"description": "Expressão matemática (ex: '2 + 2')",
}
},
"required": ["expressao"],
},
),
Tool(
name="buscar_clima",
description="Busca a previsão do tempo para uma cidade",
inputSchema={
"type": "object",
"properties": {
"cidade": {
"type": "string",
"description": "Nome da cidade",
}
},
"required": ["cidade"],
},
),
]
@server.call_tool()
async def call_tool(name: str, arguments: dict):
if name == "calcular":
try:
resultado = eval(arguments["expressao"]) # Apenas para demo!
return [TextContent(type="text", text=f"Resultado: {resultado}")]
except Exception as e:
return [TextContent(type="text", text=f"Erro: {e}")]
elif name == "buscar_clima":
cidade = arguments["cidade"]
# Simulação — em produção, chamaria uma API real
clima = {"São Paulo": "25°C, ensolarado", "Rio": "30°C, nublado"}
resultado = clima.get(cidade, "Cidade não encontrada")
return [TextContent(type="text", text=f"Clima em {cidade}: {resultado}")]
return [TextContent(type="text", text=f"Ferramenta desconhecida: {name}")]
async def main():
async with stdio_server() as (read, write):
await server.run(read, write, server.create_initialization_options())
if __name__ == "__main__":
import asyncio
asyncio.run(main())
MCP Server com recursos
Além de tools, MCP suporta resources (dados que o LLM pode ler):
@server.list_resources()
async def list_resources():
return [
Resource(
uri="file:///config.json",
name="Configuração do sistema",
description="Arquivo de configuração atual",
mimeType="application/json",
),
]
@server.read_resource()
async def read_resource(uri: str):
if uri == "file:///config.json":
config = {"ambiente": "producao", "versao": "1.0.0"}
return json.dumps(config, indent=2)
raise ValueError(f"Recurso não encontrado: {uri}")
MCP Server com prompts
@server.list_prompts()
async def list_prompts():
return [
Prompt(
name="analise_codigo",
description="Analisa um trecho de código em busca de problemas",
arguments=[
PromptArgument(
name="codigo",
description="O código para analisar",
required=True,
)
],
),
]
@server.get_prompt()
async def get_prompt(name: str, arguments: dict):
if name == "analise_codigo":
codigo = arguments["codigo"]
return GetPromptResult(
messages=[
PromptMessage(
role="user",
content=TextContent(
type="text",
text=f"Analise este código e sugira melhorias:\n\n```python\n{codigo}\n```",
),
)
]
)
Usando com Claude
O Anthropic Claude suporta MCP nativamente. Configure no claude_desktop_config.json:
{
"mcpServers": {
"meu-server": {
"command": "python",
"args": ["/path/to/mcp_server.py"]
}
}
}
Exemplo real: MCP Server para banco de dados
from mcp.server import Server
from mcp.types import Tool, TextContent
import sqlite3
server = Server("db-mcp")
@server.list_tools()
async def list_tools():
return [
Tool(
name="query_sql",
description="Executa uma query SQL SELECT no banco de dados",
inputSchema={
"type": "object",
"properties": {
"sql": {
"type": "string",
"description": "Query SQL SELECT",
}
},
"required": ["sql"],
},
),
Tool(
name="listar_tabelas",
description="Lista todas as tabelas do banco",
inputSchema={"type": "object", "properties": {}},
),
]
@server.call_tool()
async def call_tool(name: str, arguments: dict):
conn = sqlite3.connect("meubanco.db")
if name == "query_sql":
sql = arguments["sql"]
if not sql.strip().upper().startswith("SELECT"):
return [TextContent(type="text", text="Erro: apenas SELECT permitido")]
cursor = conn.execute(sql)
colunas = [desc[0] for desc in cursor.description]
linhas = cursor.fetchall()
resultado = f"Colunas: {colunas}\n"
for linha in linhas[:10]: # Limitar a 10 linhas
resultado += f"{linha}\n"
return [TextContent(type="text", text=resultado)]
elif name == "listar_tabelas":
cursor = conn.execute(
"SELECT name FROM sqlite_master WHERE type='table'"
)
tabelas = [row[0] for row in cursor.fetchall()]
return [TextContent(type="text", text=f"Tabelas: {tabelas}")]
conn.close()
Ecossistema MCP
Servers MCP já disponíveis:
| Server | O que faz |
|---|---|
| GitHub | Repositórios, issues, PRs |
| Slack | Mensagens, canais |
| PostgreSQL | Queries em banco |
| Filesystem | Ler/esverver arquivos |
| Puppeteer | Automação de navegador |
| Google Drive | Arquivos e pastas |
| Notion | Páginas e databases |
Conclusão
MCP é o protocolo que vai padronizar como IAs interagem com o mundo. Em vez de integrações custom para cada serviço, temos um padrão aberto que qualquer LLM e qualquer ferramenta pode implementar.
Comece criando um MCP Server simples para uma ferramenta que você usa. Em poucas horas, qualquer LLM que suporte MCP poderá usar sua ferramenta.
Caso eu tenha falado alguma besteira, por favor, agradecerei correções e sugestões.