Extra Inteligência Artificial • Trilha Progressiva em 4 Níveis


🧭 Navegação Pedagógica


🎯 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:

  1. Gerar o JSON da requisição tools/list.
  2. Criar a resposta estruturada com duas ferramentas: ler_arquivo e calcular_soma.
  3. Validar a presença dos campos jsonrpc, id e result.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)

  1. Salve o arquivo como: Atividade_10_1_SeuNome
  2. 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()