Skip to main content
Glama
lucas-moont

mcp-lab-01-notes-server

by lucas-moont

mcp-lab-01-notes-server

Nível 01 da trilha MCP Lab: primeiro servidor MCP construído com o SDK oficial (mcp no PyPI). Domínio: um gerenciador de notas e tarefas guardadas como arquivos markdown locais.

Termos técnicos seguem o glossário em ../CONTEXT.md.

O que este Server faz

5 Tools sobre uma pasta de arquivos .md:

Tool

O que faz

create_note(title, content="", is_task=False)

Cria uma nota; com is_task=True ela nasce como tarefa (status: pending)

list_notes()

Lista todas as notas com título e status

read_note(slug)

Devolve o corpo completo de uma nota

mark_done(slug)

Marca uma tarefa como concluída

delete_note(slug)

Apaga uma nota

flowchart LR
    subgraph server.py [camada de protocolo]
        T[Tools do MCPServer]
    end
    subgraph note.py [domínio]
        N[Note, slugify, parse, render]
    end
    subgraph storage.py [armazenamento]
        S[NotesStorage: ler/escrever/apagar .md]
    end

    T -->|delega| N
    T -->|delega| S
    N -.->|não conhece| S
    S -.->|não conhece| N

server.py é a única camada que conhece as duas outras. note.py (regra de negócio) e storage.py (arquivos) não se conhecem entre si — isso é proposital: dá pra trocar onde as notas são guardadas (um banco de dados, por exemplo) sem tocar no que é uma Nota.

Como rodar

uv sync
uv run pytest -q        # 33 testes
uv run ruff check .
uv run mypy

Por padrão as notas vão para ~/.mcp-lab/notes. Pra usar outra pasta:

NOTES_SERVER_DIR=/caminho/qualquer uv run notes-server

Usando de verdade no Claude Code

claude mcp add notes-server -- uv run --directory "$(pwd)" notes-server

Depois disso, numa conversa do Claude Code, peça pra ele criar uma nota ou listar suas tarefas — o modelo vai decidir sozinho quando chamar cada Tool.

Estrutura do código

src/notes_server/
├── storage.py   → só sabe ler/escrever/apagar arquivos; barra path traversal
├── note.py      → o que é uma Note; slugify; frontmatter -> Note e Note -> frontmatter
└── server.py    → liga os Tools do MCP ao domínio; ToolError pros erros esperados

Um .md por camada em docs/, explicando o pra-quê/o-quê/como de cada uma:

O que este nível deliberadamente NÃO faz

  • Não expõe as notas como Resources nem tem Prompts prontos — isso é o Nível 02-resources-prompts.

  • Não valida concorrência (dois processos escrevendo a mesma nota ao mesmo tempo) — fora de escopo pra um projeto local de estudo.

  • O frontmatter é um parser feito à mão, de propósito (ver docs/02-dominio-nota.md) — não é um formato geral de YAML.

Referência oficial

modelcontextprotocol.io para a spec do protocolo. github.com/modelcontextprotocol/python-sdk para o código-fonte do SDK — o pacote mcp mudou de FastMCP para MCPServer na versão 2.x; se você ler isto muito depois, confira se a API ainda bate com o que está aqui.