Skip to main content
Glama
lucaszarzur

CherryTree MCP Server

by lucaszarzur
README.md
# CherryTree MCP Server

MCP server que expõe leitura e escrita de arquivos CherryTree `.ctd` (XML) como ferramentas nativas do Claude Code.

Suporta rich text, codeboxes, tabelas, imagens, âncoras e bookmarks. Todas as escritas passam por auditoria byte-a-byte automática comparando o backup com o arquivo resultante no disco.

## Tools disponíveis

### Leitura
- `list_nodes` — listar nodes da árvore (com profundidade e breadcrumb)
- `read_node` — ler conteúdo de um node (texto, formatação, widgets)
- `search_nodes` — busca full-text em todos os nodes
- `list_bookmarks` — listar nodes marcados como favoritos

### Escrita
- `create_node` — criar node (texto plano ou XML rico via `content_xml`)
- `create_node_with_codebox` — criar node com codebox (ou XML rico via `content_xml`)
- `update_node_content` — substituir ou append (texto plano ou XML rico via `content_xml`)
- `append_codebox_to_node` — adicionar codebox ou XML rico a node existente
- `update_node_properties` — alterar nome, tags, ícone, cor, readonly
- `delete_node` — deletar node e filhos
- `move_node` — mover node para outro pai

### Bookmarks
- `add_bookmark` — adicionar node aos favoritos
- `remove_bookmark` — remover node dos favoritos

## Rich Text (`content_xml`)

Os tools de escrita aceitam `content_xml` para formatação completa do CherryTree:

```xml
<rich_text scale="h1" foreground="#00000000ffff" weight="heavy">Título</rich_text>
<rich_text>
Texto normal com </rich_text>
<rich_text weight="heavy">negrito</rich_text>
<rich_text> e </rich_text>
<rich_text style="italic">itálico</rich_text>
<rich_text foreground="#e66100" weight="heavy"> e laranja bold</rich_text>
<rich_text link="node 42">link interno</rich_text>
```

### Atributos suportados em `<rich_text>`

| Atributo | Valores | Exemplo |
|----------|---------|---------|
| `weight` | `heavy` | bold |
| `foreground` | `#RRRRGGGGBBBB` (48-bit GTK) | `#00000000ffff` (azul) |
| `background` | `#RRRRGGGGBBBB` | highlight |
| `style` | `italic` | itálico |
| `underline` | `single` | sublinhado |
| `strikethrough` | `true` | riscado |
| `scale` | `h1`-`h6`, `small`, `sup`, `sub` | headings |
| `family` | `monospace` | monoespaçado |
| `justification` | `left`, `center`, `right`, `fill` | alinhamento |
| `link` | `webs URL`, `node UID`, `file BASE64`, `fold BASE64` | links |
| `indent` | `1`-`3` | indentação |

### Widgets (posicionados por `char_offset`)

Widgets são renderizados inline na posição `char_offset` (contagem de chars no texto concatenado dos `<rich_text>`). Cada widget ocupa exatamente 1 caractere no buffer.

```xml
<codebox char_offset="42" justification="left" frame_width="700"
         frame_height="200" width_in_pixels="1"
         syntax_highlighting="python3" highlight_brackets="1"
         show_line_numbers="0">print("hello")</codebox>

<table char_offset="100" col_min="40" col_max="400"
       col_widths="200,200" is_light="0">
  <row><cell>valor1</cell><cell>valor2</cell></row>
  <row><cell>header1</cell><cell>header2</cell></row>
</table>

<encoded_png char_offset="50" anchor="nome_ancora"/>
```

## Arquitetura

- **Leituras** usam `lxml` para parsing/queries XML (seguro, sem write-back)
- **Escritas** usam manipulação de string raw para evitar normalização de `\r` que corrompe `char_offset` em nodes não editados (bug do `lxml`/`ET` ao serializar)
- **Backup** com timestamp criado automaticamente antes de cada escrita em `.cherrytree-backups/` (mantém os últimos 10)
- **Auditoria** byte-a-byte após cada escrita: lê backup e arquivo novo do disco, compara prefixo/sufixo, identifica node alterado, conta total de nodes, valida XML

### Backups

Toda operação de escrita cria um backup **antes** de modificar o arquivo:

```
Documents/.cherrytree-backups/
  Anotações_20260821_000345.ctd
  Anotações_20260821_000639.ctd
  Anotações_20260821_001800.ctd
  ...
```

- Formato: `{nome}_{YYYYMMDD_HHMMSS}.ctd`
- Retenção: últimos 10 backups (mais antigos são removidos automaticamente)
- Localização: subpasta `.cherrytree-backups/` no mesmo diretório do arquivo `.ctd`

Para restaurar manualmente:
```bash
cp "Documents/.cherrytree-backups/Anotações_20260821_000345.ctd" "Documents/Anotações.ctd"
```

### Formato de auditoria

Toda operação de escrita retorna um relatório como:

```
[AUDIT] readback 45,120,109 bytes: OK
  delta: +252 bytes (45,119,857 -> 45,120,109)
  change region: bak[45,119,844:45,119,844] -> disk[45,119,844:45,120,096]
  prefix (45,119,844 bytes): OK
  suffix (13 bytes): OK
  nodes: 5304 (backup) -> 5305 (disco) [+1]
  node adicionado: 6481 "Nome do Node" (alvo)
  integridade: OK
  XML parse: OK
```

Se qualquer byte fora da região alvo diferir entre backup e disco, o relatório exibe `CORRUPTED!` e `INTEGRITY FAILURE`.

Todas as write tools retornam o relatório de auditoria na resposta. Em caso de falha no XML parse, o backup é restaurado automaticamente:

```
  XML parse: FAILED — <detalhes do erro>
  ROLLBACK: backup restaurado automaticamente
```

## Instalação

### 1. Criar virtualenv e instalar dependências

```bash
cd ~/cherrytree-mcp
python3 -m venv .venv
.venv/bin/pip install -e .
```

### 2. Configurar o MCP no Claude Code

```bash
claude mcp add cherrytree -s user \
  -e CHERRYTREE_FILE="/caminho/para/seu/arquivo.ctd" \
  -- /caminho/para/cherrytree-mcp/.venv/bin/python \
     /caminho/para/cherrytree-mcp/server.py
```

### 3. Reiniciar o Claude Code

As tools aparecem automaticamente como `mcp__cherrytree__<tool_name>`.

## Variáveis de ambiente

| Variável | Descrição |
|----------|-----------|
| `CHERRYTREE_FILE` | Caminho absoluto para o arquivo `.ctd` do CherryTree |

## Requisitos

- Python >= 3.11
- CherryTree v1.x (formato `.ctd` XML, não `.ctb` SQLite)
- Dependências: `mcp[cli]>=1.0.0`, `lxml>=5.0.0`

## Limitações

- Apenas formato `.ctd` (XML). Arquivos `.ctb` (SQLite) não são suportados.
- O CherryTree precisa ser recarregado (fechar/abrir ou trocar de node) após edições via MCP para refletir as mudanças na UI.
- Operações de escrita com `append=False` em `update_node_content` substituem todo o conteúdo do node (texto, codeboxes, imagens, tabelas).

TDQS

A4/5.0

Scored across 13 tools

Disambiguation4/5

Most tools target distinct actions (list, read, search, create, update, delete, move, bookmark), so an agent can generally select correctly. The only mild overlap is create_node and create_node_with_codebox, since create_node can also embed codeboxes via content_xml, but the dedicated helper is clearly specialized.

Naming Consistency5/5

Tool names uniformly follow a verb_noun pattern: list_nodes, read_node, create_node, update_node_content, delete_node, move_node, add_bookmark, remove_bookmark. Even the longer names like append_codebox_to_node and create_node_with_codebox still follow the same predictable convention.

Tool Count5/5

13 tools is a well-scoped set for a CherryTree note-management server, covering reading, searching, writing, structure manipulation, and bookmarks without redundancy or bloat. Each tool earns its place and the count feels balanced for the domain.

Completeness5/5

The tool surface covers the full lifecycle of CherryTree nodes: list, read, search, create (regular and codebox), update content, update properties, append codebox, move, delete, plus complete bookmark management. There are no obvious dead ends for common note-editing workflows.

Maintenance

ActivityMaintained
ResponsivenessNo issues