Construa um MCP Server completo que gerencia tarefas com persistência em JSON — criar, listar, atualizar e remover.
Antes de escrever qualquer código, é essencial planejar a estrutura do nosso Gerenciador de Tarefas. Vamos definir quais tools o servidor MCP vai expor, qual será a estrutura de dados de cada tarefa e como vamos organizar o projeto. Um bom planejamento agora evita retrabalho depois e garante que o servidor seja coerente e fácil de manter.
O nosso MCP Server vai expor 4 tools para o modelo: criar_tarefa (adiciona uma nova tarefa), listar_tarefas (mostra tarefas existentes com filtro por status), atualizar_tarefa (modifica título, descrição ou status) e remover_tarefa (exclui uma tarefa pelo ID). Cada tarefa terá os campos: id (UUID único), titulo, descricao, status ("pendente" ou "feita") e data_criacao. Todas as tarefas serão persistidas em um arquivo JSON local.
Sempre comece definindo as tools e seus parâmetros antes de codificar. Pense do ponto de vista do usuário: "O que eu pediria ao Claude para fazer com minhas tarefas?". Cada pedido natural se transforma em uma tool. "Crie uma tarefa" → criar_tarefa. "Me mostre as pendentes" → listar_tarefas(status="pendente"). Essa abordagem top-down garante que o servidor seja intuitivo.
O servidor MCP principal — importa FastMCP, define as 4 tools e inicia o servidor. Toda a lógica fica aqui.
Arquivo de persistência — criado automaticamente pelo servidor. Contém a lista de tarefas em formato JSON.
Registrar o servidor no claude_desktop_config.json para que o Claude possa usar as tools automaticamente.
Para persistir as tarefas entre sessões, usaremos um arquivo tarefas.json. É simples, legível, não requer dependências externas e funciona perfeitamente para projetos locais. Vamos criar funções auxiliares para ler e salvar dados nesse arquivo, usando o módulo pathlib para gerenciar caminhos de forma segura e multiplataforma.
A estrutura JSON será uma lista de dicionários, onde cada dicionário representa uma tarefa. Exemplo: [{"id": "abc-123", "titulo": "Estudar MCP", "descricao": "Completar trilha 4", "status": "pendente", "data_criacao": "2025-01-15T10:30:00"}]. Duas funções auxiliares centralizam o acesso ao arquivo: carregar_tarefas() lê o JSON e retorna a lista (ou lista vazia se o arquivo não existir) e salvar_tarefas(tarefas) escreve a lista atualizada no arquivo. Usar pathlib.Path garante que os caminhos funcionem em qualquer sistema operacional.
A primeira tool que vamos implementar é a criar_tarefa. Ela recebe um título obrigatório e uma descrição opcional, gera um ID único usando o módulo uuid, define o status inicial como "pendente", registra a data de criação e salva tudo no arquivo JSON. É a operação mais fundamental do nosso gerenciador.
A tool é decorada com @mcp.tool() e definida como def criar_tarefa(titulo: str, descricao: str = ""). Internamente, ela: 1) carrega as tarefas existentes do JSON, 2) cria um novo dicionário com uuid.uuid4() para o ID, status "pendente" e datetime.now().isoformat() para a data, 3) adiciona à lista e salva, 4) retorna uma mensagem de confirmação com o ID gerado. O Claude recebe essa confirmação e pode informar o usuário naturalmente.
Use type hints nos parâmetros da tool — o MCP usa essas anotações para gerar automaticamente a documentação que o modelo recebe. titulo: str diz ao Claude que precisa fornecer um texto. descricao: str = "" indica que é opcional. Quanto mais claros os tipos, melhor o modelo entende como usar a tool.
Sempre use str(uuid.uuid4()) para converter o UUID em string antes de salvar no JSON. O tipo UUID do Python não é serializável por padrão pelo módulo json — se você tentar salvar um objeto UUID diretamente, vai receber um TypeError. Converter para string resolve o problema e mantém a unicidade do identificador.
A tool listar_tarefas permite ao Claude consultar as tarefas existentes, opcionalmente filtrando por status. Ela retorna uma lista formatada que o modelo pode apresentar de forma legível ao usuário, incluindo a contagem total de resultados. É a tool mais usada — toda interação com o gerenciador provavelmente começa ou termina com uma listagem.
Definida como def listar_tarefas(status: str = "todas"), a tool carrega todas as tarefas do JSON e, se o parâmetro status for diferente de "todas", filtra apenas as que correspondem ("pendente" ou "feita"). O retorno deve ser uma string formatada com cada tarefa mostrando: título, status, descrição (se houver) e data de criação. Inclua sempre a contagem total no início: "Encontradas X tarefas". Se não houver tarefas, retorne uma mensagem clara como "Nenhuma tarefa encontrada."
Tools de consulta como listar_tarefas são tipicamente as mais chamadas em qualquer MCP Server — representam cerca de 60-70% das interações. Por isso, invista tempo formatando bem o retorno. O modelo usa esse texto para compor a resposta ao usuário. Quanto mais claro e estruturado o retorno da tool, melhor será a resposta final que o Claude gera para o usuário.
As tools de atualizar_tarefa e remover_tarefa completam o CRUD do nosso gerenciador. Ambas recebem o ID da tarefa como parâmetro obrigatório e precisam validar que esse ID realmente existe antes de executar qualquer operação. A atualização permite mudar título, descrição e/ou status. A remoção exclui permanentemente a tarefa.
A tool atualizar_tarefa(id: str, titulo: str = None, descricao: str = None, status: str = None) busca a tarefa pelo ID, atualiza apenas os campos fornecidos (os que não forem None) e salva. A tool remover_tarefa(id: str) localiza a tarefa pelo ID e a remove da lista. Ambas devem validar que o ID existe — se não existir, retornam uma mensagem de erro clara como "Tarefa com ID 'xyz' não encontrada." Isso evita que o modelo fique confuso tentando operar sobre tarefas inexistentes.
Use parâmetros opcionais com None como padrão na tool de atualização. Assim, o Claude pode atualizar apenas o campo necessário sem precisar reenviar todos os dados. Se o usuário diz "marque como feita", o modelo chama atualizar_tarefa(id="abc", status="feita") — título e descrição ficam inalterados porque são None.
Sempre valide o ID! Se o modelo tentar atualizar ou remover uma tarefa com um ID que não existe, nunca retorne silêncio ou uma exceção não tratada. Retorne uma mensagem de erro clara e descritiva. Sem essa validação, o Claude pode achar que a operação foi bem-sucedida e informar o usuário incorretamente — gerando uma experiência confusa e dados inconsistentes.
Com as 4 tools implementadas, é hora de testar o Gerenciador de Tarefas de ponta a ponta. Vamos configurar o servidor no Claude Desktop e percorrer um cenário completo: criar tarefas, listar, atualizar status e remover. Esse teste valida não apenas o código, mas a experiência de uso via linguagem natural.
Configure o servidor no claude_desktop_config.json adicionando a entrada com o comando para executar o server.py. Reinicie o Claude Desktop e verifique se as 4 tools aparecem no ícone de ferramentas. A partir daí, todas as interações são em linguagem natural — o Claude decide sozinho qual tool chamar com base no que o usuário pede.
"Crie uma tarefa para estudar MCP com a descrição: Completar a trilha 4 do curso". O Claude deve chamar criar_tarefa e confirmar com o ID gerado.
"Liste todas as minhas tarefas" e depois "Mostre apenas as pendentes". O Claude deve chamar listar_tarefas com e sem filtro de status.
"Marque a tarefa de estudar MCP como feita". O Claude deve usar o ID da tarefa e chamar atualizar_tarefa com status="feita".
"Remova a tarefa que acabei de completar". O Claude deve chamar remover_tarefa com o ID correto e confirmar a exclusão.
Se algo não funcionar, verifique o terminal onde o servidor está rodando — erros de Python aparecerão lá. Problemas comuns: caminho errado no config, import faltando, ou erro de serialização JSON. Use print() para debug temporário e verifique se o arquivo tarefas.json está sendo criado e atualizado corretamente no diretório do projeto.
Próximo Módulo: 4.2 — Consultor de Banco de Dados