🧩 Exercícios: Model Context Protocol (MCP)
Extra Inteligência Artificial • Trilha Progressiva em 4 Níveis
🧭 Navegação Pedagógica
-
📖 Teoria do Capítulo 💻 Exemplos 📊 Slides 🧠 Quiz
🎯 Nível 1: Fundamentos
Problema 10.1 — Mensagens JSON-RPC 2.0 do Protocolo MCP
Contexto: Construir a estrutura de payload JSON-RPC 2.0 padrão para a inicialização e listagem de ferramentas de um servidor MCP via transporte standard I/O (stdio).
Requisitos de Execução:
- Gerar o JSON da requisição
tools/list. - Criar a resposta estruturada com duas ferramentas:
ler_arquivoecalcular_soma. - Validar a presença dos campos
jsonrpc,ideresult.tools.
Resultado Esperado
Servidor MCP respondeu com 2 ferramentas registradas:
- ler_arquivo (desc: Lê arquivos em disco)
- calcular_soma (desc: Soma dois números inteiros)
📤 Instruções de Entrega (Microsoft Teams)
- Salve o arquivo como:
Atividade_10_1_SeuNome - Envie na tarefa:
Atividade Cap 10 - Model Context Protocol (MCP)
🔑 Gabarito de Código & Solução Comentada
# mcp_jsonrpc.py
import json
def responder_tools_list(request_id):
resposta = {
"jsonrpc": "2.0",
"id": request_id,
"result": {
"tools": [
{
"name": "ler_arquivo",
"description": "Lê arquivos em disco",
"inputSchema": {
"type": "object",
"properties": {"caminho": {"type": "string"}},
"required": ["caminho"]
}
},
{
"name": "calcular_soma",
"description": "Soma dois números inteiros",
"inputSchema": {
"type": "object",
"properties": {
"a": {"type": "integer"},
"b": {"type": "integer"}
},
"required": ["a", "b"]
}
}
]
}
}
print(f"Servidor MCP respondeu com {len(resposta['result']['tools'])} ferramentas registradas:")
for t in resposta["result"]["tools"]:
print(f"- {t['name']} (desc: {t['description']})")
return resposta
if __name__ == "__main__":
responder_tools_list("req-1")
🎯 Nível 2: Prática
Problema 10.2 — Implementação de um Servidor MCP com FastMCP
Crie um servidor MCP usando o framework FastMCP em Python que exponha uma Tool para converter moedas e um Resource com as cotações em cache.
🔑 Gabarito de Código & Solução Comentada
# fastmcp_server.py
# Exemplo conceitual compatível com a biblioteca oficial mcp
class MiniFastMCP:
def __init__(self, nome):
self.nome = nome
self.tools = {}
self.resources = {}
def tool(self):
def decorator(func):
self.tools[func.__name__] = func
return func
return decorator
def resource(self, uri):
def decorator(func):
self.resources[uri] = func
return func
return decorator
app = MiniFastMCP("FinancasServer")
@app.tool()
def converter_dolar_para_real(valor: float) -> float:
"""Converte valor em dólares para reais usando cotação fixa de 5.50."""
return valor * 5.50
@app.resource("cotacoes://atual")
def obter_cotacoes():
return {"USD_BRL": 5.50, "EUR_BRL": 6.00}
🎯 Nível 3: Integração
Problema 10.3 — Cliente MCP: Descoberta e Execução Dinâmica de Ferramentas
Implemente um cliente que conecte em um servidor MCP, receba o catálogo de ferramentas, injete-as dinamicamente no formato esperado pelo LLM e invoque tools/call.
🔑 Gabarito de Código & Solução Comentada
# mcp_client.py
class MCPClient:
def __init__(self, server):
self.server = server
def listar_ferramentas_para_llm(self):
return [
{
"type": "function",
"function": {
"name": nome,
"description": func.__doc__ or "Sem descrição",
}
}
for nome, func in self.server.tools.items()
]
def executar_ferramenta(self, nome, **kwargs):
if nome in self.server.tools:
return self.server.tools[nome](**kwargs)
raise ValueError(f"Ferramenta {nome} não encontrada no servidor MCP.")
🎯 Nível 4: Desafio
Problema 10.4 — Servidor MCP Seguro com Sandboxing e Controle de Acesso
Implemente um middleware de segurança para servidor MCP que intercepte todas as invocações de tools/call, barrando comandos perigosos e limitando acesso apenas a caminhos autorizados de filesystem.
🔑 Gabarito de Código & Solução Comentada
# mcp_security_guard.py
import os
class SafeMCPServer:
def __init__(self, pasta_permitida):
self.pasta_permitida = os.path.abspath(pasta_permitida)
def executar_leitura(self, caminho_arquivo):
caminho_absoluto = os.path.abspath(caminho_arquivo)
# Prevenção rigorosa de Path Traversal (../../etc/passwd)
if not caminho_absoluto.startswith(self.pasta_permitida):
raise PermissionError("Acesso Negado: Tentativa de violação de sandbox MCP!")
with open(caminho_absoluto, "r", encoding="utf-8") as f:
return f.read()