Pular para o conteúdo
Inteligência Artificial

Pensieve: notas com API, MCP e Skill para a sua IA

A página inicial do Pensieve com o título Anote. Lembre. Pronto., o botão Começar grátis e, ao lado, um mural com três notas e um balão da IA dizendo que anotou Pagar o DAS na lista Contas

Olá meus Unicórnios! 🦄✨

Sabe aquela ideia que aparece no meio de uma reunião, aquela conta que vence dia 20, aquele "preciso lembrar de ligar para o dentista amanhã"? Eu anotava isso em três lugares diferentes e esquecia nos três. 😅

Foi daí que nasceu o Pensieve, um app de notas com lembretes que eu fiz. Quem leu Harry Potter reconhece o nome: é a penseira, a bacia onde se guardam as lembranças. Aqui a bacia é um mural de notas, e ela ainda avisa na hora certa. ✨

E como eu passo o dia conversando com IA, ele nasceu programável: tem uma API REST, um servidor MCP para o Claude, o ChatGPT e o Cursor, e uma Skill pronta para o Claude Code. Neste artigo eu mostro como o app funciona e depois cada uma dessas portas de entrada, com chamadas de verdade e as respostas que voltaram.

PensieveApp gratuito de notas com lembretes, no navegador, no celular e no computador, com API, MCP e Skill para IA.pensieve.com.br

🧠 Como o Pensieve funciona

A ideia é ser simples a ponto de não dar preguiça. Uma nota é texto livre, sem título e sem formatação, com até 10 mil caracteres. Você digita, aperta Enter, e ela está salva.

Organizar é opcional. Quem quiser tem três ferramentas:

  • Listas, com nome e uma de oito cores. A nota ganha a cor da lista no mural.
  • Favoritas, que ficam sempre no topo.
  • Busca que ignora acento e maiúscula e acha pelo começo da palavra: "backu" encontra "backups".
A seção Organizar do Pensieve, com as oito cores de lista à esquerda e, à direita, um mural de exemplo com a barra lateral de Favoritas, Com alerta e Sem lista e sete notas coloridas pelas listas Trabalho, Casa e Contas

A parte de que eu mais gosto são os lembretes escritos em português. Você escreve "ligar pro dentista amanhã às 10h" e o Pensieve entende: a nota fica "ligar pro dentista" e o "amanhã às 10h" vira o aviso. Ele entende também repetição ("todo dia 5", "toda terça e quinta", "a cada 15 dias") e fim de série ("por 7 dias", "10 vezes"). E só cria o lembrete quando tem certeza: "reunião de segunda foi boa" continua sendo só uma nota. 😉

A seção Lembretes escritos como você fala, com a tabela de expressões aceitas e o campo de teste mostrando ligar pro dentista amanhã às 10h separado em nota salva ligar pro dentista e aviso Amanhã, 10:00

O aviso chega no navegador (Web Push), no celular (instalando o site como app) e num app para Windows, Mac e Linux que fica na bandeja do sistema. Tudo de graça: não existe plano pago, nem recurso trancado.

🔑 A chave da API

Tudo que vem daqui para baixo, exceto o MCP, usa uma chave pessoal. Ela é gerada dentro do app, em Minha conta › API, e começa com pk_.

Três coisas que vale saber antes de gerar:

  • A chave aparece uma única vez. O Pensieve guarda só o hash dela, então copie na hora.
  • Ela dá acesso total às suas notas. Trate como senha.
  • Dá para ter até 10 chaves por conta. Crie uma por integração: se precisar revogar uma, as outras continuam funcionando.

Para não colar a chave dentro de script nenhum, guarde numa variável de ambiente. No Linux, no Mac ou no Git Bash:

export PENSIEVE_API_KEY=SUA_CHAVE_AQUI

No PowerShell do Windows, o jeito muda:

$env:PENSIEVE_API_KEY = "SUA_CHAVE_AQUI"

Essa variável vale só para aquela janela de terminal. Fechou, abriu outra, tem de definir de novo.

🌐 A API na prática

A API fica em https://www.pensieve.com.br/api/v1, fala JSON e aceita a chave no cabeçalho Authorization: Bearer. Para começar, a chamada que confirma que a chave funciona e diz de quem ela é:

curl https://www.pensieve.com.br/api/v1/me \
  -H "Authorization: Bearer $PENSIEVE_API_KEY"

A resposta traz o dono da conta. Troquei o nome e o e-mail por fictícios aqui:

{
    "user": {
        "id": 1,
        "name": "Unicórnio de Teste",
        "email": "[email protected]"
    }
}

Se a barra invertida no fim da linha for novidade: ela só diz ao terminal que o comando continua na linha de baixo. Dá para escrever tudo numa linha só, se preferir.

Criar uma nota

O único campo obrigatório é o content, o texto da nota:

curl -X POST https://www.pensieve.com.br/api/v1/notes \
  -H "Authorization: Bearer $PENSIEVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "content": "Comprar pergaminho e tinta nova para a pena" }'

A API responde 201 (não 200) com a nota criada:

{
    "note": {
        "id": 16,
        "content": "Comprar pergaminho e tinta nova para a pena",
        "listId": null,
        "isFavorite": false,
        "isArchived": false,
        "archivedAt": null,
        "remindAt": null,
        "repeat": null,
        "createdAt": "2026-09-26T01:35:30.000Z",
        "updatedAt": "2026-09-26T01:35:30.000Z",
        "deletedAt": null,
        "purgeAt": null
    }
}

Repare nos campos: listId é a lista, isFavorite a estrela, remindAt o lembrete e repeat a repetição. Os dois últimos, deletedAt e purgeAt, só se preenchem quando a nota vai para a lixeira.

Criar uma lista

Lista tem nome e cor em hexadecimal:

curl -X POST https://www.pensieve.com.br/api/v1/lists \
  -H "Authorization: Bearer $PENSIEVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Exemplo do blog", "color": "#2f7d5b" }'
{
    "list": {
        "id": 4,
        "name": "Exemplo do blog",
        "color": "#2F7D5B",
        "position": 2,
        "noteCount": 0,
        "createdAt": "2026-09-26T01:35:30.000Z"
    }
}

Mandei a cor em minúsculas e ela voltou em maiúsculas: a API normaliza. E o nome é único na conta, sem diferenciar maiúsculas. Tentei criar de novo como "exemplo do blog", tudo minúsculo, e veio um 409:

{
    "error": {
        "message": "Você já tem uma lista com esse nome.",
        "fields": {
            "name": "Nome já usado."
        }
    }
}

Um lembrete que repete

Aqui mora a parte mais legal da API. Para um lembrete que repete toda segunda e quinta às 9h, você manda três campos: remindAt (o primeiro aviso), repeat (a regra) e timeZone (o fuso):

curl -X POST https://www.pensieve.com.br/api/v1/notes \
  -H "Authorization: Bearer $PENSIEVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Alimentar a coruja",
    "listId": 4,
    "remindAt": "2026-09-28T09:00:00-03:00",
    "repeat": { "freq": "weekly", "days": [1, 4] },
    "timeZone": "America/Sao_Paulo"
  }'
{
    "note": {
        "id": 17,
        "content": "Alimentar a coruja",
        "listId": 4,
        "isFavorite": false,
        "isArchived": false,
        "archivedAt": null,
        "remindAt": "2026-09-28T12:00:00.000Z",
        "repeat": {
            "freq": "weekly",
            "interval": 1,
            "days": [
                1,
                4
            ]
        },
        "createdAt": "2026-09-26T01:35:43.000Z",
        "updatedAt": "2026-09-26T01:35:43.000Z",
        "deletedAt": null,
        "purgeAt": null
    }
}

Eu mandei 9h e voltou 12:00:00.000Z. Calma, não é erro! 😅 As respostas vêm sempre em UTC (o Z no fim), e 9h em Brasília são 12h em UTC. Na hora de mostrar para alguém, converta de volta para o fuso da pessoa.

Nos days, 0 é domingo, 1 é segunda, e assim por diante até 6, sábado. As regras de repetição são estas:

RegraO que faz
{ "freq": "daily" }todo dia
{ "freq": "daily", "interval": 15 }a cada 15 dias
{ "freq": "weekdays" }de segunda a sexta
{ "freq": "weekly", "days": [1, 4] }toda segunda e quinta
{ "freq": "monthly" }todo mês, no dia do primeiro aviso
{ "freq": "yearly" }todo ano, na data do primeiro aviso
{ "freq": "daily", "count": 7 }todo dia, 7 vezes no total
{ "freq": "weekly", "days": [2], "until": "2026-12-15" }toda terça, até 15/12 (inclusive)

Buscar, editar e adiar

A busca é o parâmetro q, e ela acha por trecho: "pergam" encontra "pergaminho".

curl "https://www.pensieve.com.br/api/v1/notes?q=pergam&limit=20" \
  -H "Authorization: Bearer $PENSIEVE_API_KEY"
{
    "notes": [
        {
            "id": 16,
            "content": "Comprar pergaminho e tinta nova para a pena",
            "listId": null,
            "isFavorite": false,
            "isArchived": false,
            "archivedAt": null,
            "remindAt": null,
            "repeat": null,
            "createdAt": "2026-09-26T01:35:30.000Z",
            "updatedAt": "2026-09-26T01:35:30.000Z",
            "deletedAt": null,
            "purgeAt": null
        }
    ],
    "total": 1,
    "limit": 20,
    "offset": 0
}

Com limit, a resposta ganha total e offset para paginar. Sem ele, vêm todas as notas do filtro de uma vez. Dá para combinar a busca com filter (favorites, alerts, nolist, archived, trash) e com listId: ?filter=alerts&listId=4 traz só as notas com lembrete daquela lista.

Para editar, o PATCH recebe só o que muda. Aqui eu favoritei a nota e movi para a lista:

curl -X PATCH https://www.pensieve.com.br/api/v1/notes/16 \
  -H "Authorization: Bearer $PENSIEVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "isFavorite": true, "listId": 4 }'

No PATCH, null significa "tirar": "listId": null tira da lista, "remindAt": null remove o lembrete e a repetição, e "repeat": null para de repetir mas mantém o próximo aviso. E "isArchived": true tira a nota do mural sem mandar para a lixeira.

Adiar é uma rota própria. O snooze joga o próximo aviso para daqui a N minutos, contando de agora:

curl -X POST https://www.pensieve.com.br/api/v1/notes/17/snooze \
  -H "Authorization: Bearer $PENSIEVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "minutes": 30 }'
{
    "note": {
        "id": 17,
        "content": "Alimentar a coruja",
        "listId": 4,
        "isFavorite": false,
        "isArchived": false,
        "archivedAt": null,
        "remindAt": "2026-09-26T02:05:55.000Z",
        "repeat": {
            "freq": "weekly",
            "interval": 1,
            "days": [
                1,
                4
            ]
        },
        "createdAt": "2026-09-26T01:35:43.000Z",
        "updatedAt": "2026-09-26T01:35:55.000Z",
        "deletedAt": null,
        "purgeAt": null
    }
}

A chamada saiu às 01:35:55 em UTC, e o remindAt foi para 02:05:55, meia hora depois. A regra de repetição continua lá: depois desse aviso adiado, a série volta ao horário normal.

Excluir não é apagar

O DELETE responde 204, sem corpo nenhum, e manda a nota para a lixeira:

curl -X DELETE https://www.pensieve.com.br/api/v1/notes/18 \
  -H "Authorization: Bearer $PENSIEVE_API_KEY"

Ela aparece no filtro trash, agora com deletedAt e purgeAt preenchidos:

{
    "notes": [
        {
            "id": 18,
            "content": "Polir a varinha",
            "listId": 4,
            "isFavorite": false,
            "isArchived": false,
            "archivedAt": null,
            "remindAt": "2026-10-01T23:00:00.000Z",
            "repeat": {
                "freq": "weekly",
                "interval": 1,
                "days": [
                    1,
                    4
                ]
            },
            "createdAt": "2026-09-26T01:35:44.000Z",
            "updatedAt": "2026-09-26T01:36:08.000Z",
            "deletedAt": "2026-09-26T01:36:08.000Z",
            "purgeAt": "2026-10-26T01:36:08.000Z"
        }
    ]
}

O purgeAt é a data em que ela some de vez: 30 dias depois. Até lá, um POST /notes/18/restore traz a nota de volta, com lembrete e tudo. Apagar na hora é o DELETE /notes/18/permanent, e ele só funciona com a nota já na lixeira. Tentei com a nota fora dela e veio 404, "Nota não encontrado(a)". É uma trava de propósito: ninguém apaga para sempre sem passar pela lixeira. 🗑️

Várias notas de uma vez

Para importar uma lista de tarefas, o /notes/batch cria de 1 a 50 notas numa chamada só. E ele é tudo ou nada: mandei duas notas, a segunda vazia, e a resposta foi um 422 apontando exatamente qual:

{
    "error": {
        "message": "Verifique os dados informados.",
        "fields": {
            "notes.1.content": "A nota não pode ficar vazia."
        }
    }
}

O notes.1 é a segunda nota (a contagem começa no zero). Conferi as contagens da conta depois: a primeira nota, que estava certa, também não foi criada. Nada de lote salvo pela metade.

⏰ As armadilhas das datas

Se você só for ler um pedaço deste artigo, leia este. 🙏 Quase todo erro com a API do Pensieve vai ser de data.

1. Data sem fuso é recusada. Mandei um lembrete com "remindAt": "2026-09-28T09:00:00", sem o -03:00 no fim, e veio 422:

{
    "error": {
        "message": "Verifique os dados informados.",
        "fields": {
            "remindAt": "Data/hora inválida."
        }
    }
}

A mensagem diz "inválida", mas a data está certinha. O que falta é o fuso. Sem ele, 9h de onde? A API prefere recusar a adivinhar. Mande sempre -03:00 (Brasília) ou o horário em UTC com Z.

2. O primeiro aviso pode mudar de dia. Criei uma nota com a regra "segunda e quinta", mas com o remindAt numa quarta, 30/09 às 20h. O aviso voltou assim:

"remindAt": "2026-10-01T23:00:00.000Z"

Isso é quinta, 01/10, às 20h de Brasília. Como quarta não está na regra, a API pulou para o próximo dia válido. Faz sentido, mas se o seu código mostrar para a pessoa "lembrete marcado para quarta" usando o que enviou, vai mentir. Confira sempre o remindAt que voltou.

3. Repetição tem regras próprias. Duas combinações dão 422. repeat sem remindAt:

{
    "error": {
        "message": "Defina a data e a hora do primeiro aviso.",
        "fields": {
            "repeat": "Escolha a data e a hora."
        }
    }
}

E count junto com until, porque a série termina por um ou pelo outro:

{
    "error": {
        "message": "Verifique os dados informados.",
        "fields": {
            "repeat.count": "Escolha data final ou número de vezes, não os dois."
        }
    }
}

Repare que todo erro vem no mesmo formato: uma message em português e, em fields, o campo exato que precisa de conserto. Dá para mostrar isso direto para quem está usando o seu sistema.

🪤 O acento que virou interrogação

Esta me pegou no meio do caminho. Criei no lote uma nota "Devolver o livro de feitiços", com o JSON escrito direto no -d do curl, no Git Bash do Windows. A API respondeu 201, tudo lindo, e a nota foi salva assim:

"content": "Devolver o livro de feiti�os"

O "ç" virou "�". 😳 A culpa não é da API: é o caminho entre o terminal e o curl no Windows, que entregou o texto sem ser em UTF-8. A saída é tirar o JSON da linha de comando. Crie um arquivo nota.json num editor que salve em UTF-8 (o VS Code já salva assim):

{ "content": "Devolver o livro de feitiços" }

E mande o arquivo com --data-binary e um @ antes do nome:

curl -X POST https://www.pensieve.com.br/api/v1/notes \
  -H "Authorization: Bearer $PENSIEVE_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @nota.json

Aí o "feitiços" chegou inteiro. O --data-binary manda o arquivo exatamente como está, byte a byte. E se você vai escrever notas com acento de verdade, o script em Node logo abaixo não tem esse problema.

🟩 Um script em Node, sem instalar nada

O curl é ótimo para experimentar, mas para usar no dia a dia um script é mais confortável. Este aqui cria uma nota, cria um lembrete, busca, manda para a lixeira e, de propósito, tenta um lembrete sem fuso para ver o erro. Ele usa o fetch que já vem no Node 18 ou mais novo: não precisa de npm install nenhum.

Salve como notas.js:

// notas.js: cria, busca e apaga notas no Pensieve usando só o fetch do Node 18+
// Rode com: PENSIEVE_API_KEY=sua_chave node notas.js

const BASE = "https://www.pensieve.com.br/api/v1";
const CHAVE = process.env.PENSIEVE_API_KEY;

if (!CHAVE) {
    console.error("Defina a variável de ambiente PENSIEVE_API_KEY.");
    process.exit(1);
}

async function chamarApi(metodo, caminho, corpo) {
    const resposta = await fetch(BASE + caminho, {
        method: metodo,
        headers: {
            "Authorization": "Bearer " + CHAVE,
            "Content-Type": "application/json",
        },
        body: corpo ? JSON.stringify(corpo) : undefined,
    });

    // O DELETE responde 204, sem corpo nenhum: chamar .json() aqui daria erro
    if (resposta.status === 204) {
        return null;
    }

    const dados = await resposta.json();

    // resposta.ok aceita 200 e 201 (criar nota devolve 201, não 200)
    if (!resposta.ok) {
        const campos = JSON.stringify(dados.error.fields || {});
        throw new Error(`HTTP ${resposta.status}: ${dados.error.message} ${campos}`);
    }

    return dados;
}

async function criarNota(texto) {
    const dados = await chamarApi("POST", "/notes", { content: texto });
    return dados.note;
}

async function criarLembrete(texto, dataHora) {
    // A data PRECISA ter o fuso no fim (-03:00). Sem ele, a API responde 422.
    const dados = await chamarApi("POST", "/notes", {
        content: texto,
        remindAt: dataHora,
        timeZone: "America/Sao_Paulo",
    });
    return dados.note;
}

async function buscarNotas(trecho) {
    const dados = await chamarApi("GET", "/notes?q=" + encodeURIComponent(trecho));
    return dados.notes;
}

async function apagarNota(id) {
    await chamarApi("DELETE", "/notes/" + id);
}

async function principal() {
    try {
        const nota = await criarNota("Comprar penas de escrever e um tinteiro");
        console.log("Nota criada:", nota.id, "-", nota.content);

        const lembrete = await criarLembrete("Levar a coruja ao veterinário", "2026-10-02T15:30:00-03:00");
        console.log("Lembrete criado:", lembrete.id, "- avisa em", lembrete.remindAt);

        const achadas = await buscarNotas("tinteiro");
        console.log("Busca por 'tinteiro':", achadas.length, "nota(s)");

        await apagarNota(nota.id);
        console.log("Nota", nota.id, "foi para a lixeira");

        // De propósito: uma data sem fuso, para ver o erro
        await criarLembrete("Esta não vai ser salva", "2026-10-02T15:30:00");
    } catch (erro) {
        console.error("Deu erro:", erro.message);
    }
}

principal();

Dois detalhes do chamarApi evitam bugs que eu já vi muita gente cometer:

  • O if do 204 vem antes do .json(). O DELETE responde sem corpo, e resposta.json() num corpo vazio estoura um SyntaxError. Sem esse if, a nota vai para a lixeira e o seu script acusa erro assim mesmo.
  • O teste é resposta.ok, não status === 200. Criar nota devolve 201. Quem escreve === 200 na mão trata toda criação como falha.

Para rodar, no Linux, no Mac ou no Git Bash, a variável vai na frente do comando:

PENSIEVE_API_KEY=SUA_CHAVE_AQUI node notas.js

No PowerShell, defina a variável antes e rode em seguida:

$env:PENSIEVE_API_KEY = "SUA_CHAVE_AQUI"
node notas.js

A saída:

Nota criada: 22 - Comprar penas de escrever e um tinteiro
Lembrete criado: 23 - avisa em 2026-10-02T18:30:00.000Z
Busca por 'tinteiro': 1 nota(s)
Nota 22 foi para a lixeira
Deu erro: HTTP 422: Verifique os dados informados. {"remindAt":"Data/hora inválida."}

A última linha é o erro de propósito, e ele aparece com o campo exato que falhou. O lembrete das 15h30 de Brasília voltou como 18h30 em UTC, igualzinho ao do curl. E esquecendo a variável, o script para logo na primeira linha útil:

Defina a variável de ambiente PENSIEVE_API_KEY.

📖 A documentação interativa

Não precisa decorar nada disso. A API tem uma referência interativa em /api/v1/docs, gerada da especificação OpenAPI 3.1. Lá estão todos os endpoints, com os parâmetros e as respostas.

A documentação interativa da Pensieve API, versão 1.0.0 e OAS 3.1, com o resumo de autenticação, formato, datas, lembretes e erros, o botão Authorize e a primeira rota, GET /me

O botão Authorize recebe a sua chave e deixa testar as chamadas ali mesmo, pelo navegador. E o arquivo /api/v1/openapi.json importa direto no Postman ou no Insomnia, com todas as rotas prontas.

Os erros que você pode encontrar cabem numa tabela:

CódigoQuando acontece
401Chave ausente (API_KEY_MISSING) ou inválida e revogada (API_KEY_INVALID)
404A nota ou a lista não existe, ou é de outra conta
409Já existe uma lista com esse nome
422Dado inválido; o campo vem em fields
429Mais de 120 requisições por minuto com a mesma chave

O 401 sem chave nenhuma já diz o que fazer:

{
    "error": {
        "message": "Informe sua API Key no cabeçalho Authorization: Bearer pk_…",
        "code": "API_KEY_MISSING"
    }
}

🧩 A Skill: a IA aprende a usar a API

Uma Skill é um arquivo Markdown com nome, descrição e instruções, no formato Agent Skills. Ela não é código: é um manual que a IA lê e segue. A do Pensieve fica publicada em https://www.pensieve.com.br/api/v1/skill.md e ensina ao agente os endpoints, as datas com fuso, os lembretes recorrentes e as boas maneiras.

O arquivo começa com um cabeçalho (o frontmatter, entre duas linhas de ---) com o nome pensieve e uma descrição. A descrição termina assim:

Use quando a pessoa pedir para anotar algo, lembrar de algo numa data/hora ou com frequência, adiar um lembrete, ou organizar/consultar suas notas e listas no Pensieve.

Quando você pede "me lembra de pagar o aluguel todo dia 5", essa descrição é o que faz a IA perceber que a Skill serve para o pedido. E o resto do arquivo diz como agir. Algumas regras que estão lá dentro:

  • Nunca mostrar, repetir ou registrar a chave nas respostas.
  • Buscar antes de editar (GET /notes?q=trecho) e perguntar se vier mais de uma nota. Nada de adivinhar o id.
  • Perguntar antes de criar uma lista que não existe.
  • Confirmar antes de excluir, citando o texto da nota.
  • Se a pessoa não disser o fuso, usar America/Sao_Paulo.

Para instalar no Claude Code, a Skill vai numa pasta com o nome dela, dentro de ~/.claude/skills. O ~ é a sua pasta de usuário. O mkdir -p cria a pasta (e as de cima, se faltarem), e o curl -o baixa o arquivo com o nome certo:

mkdir -p ~/.claude/skills/pensieve
curl -o ~/.claude/skills/pensieve/SKILL.md https://www.pensieve.com.br/api/v1/skill.md

Depois é só deixar a chave na variável PENSIEVE_API_KEY, como no começo do artigo. É esse o nome que a Skill manda a IA usar nos comandos.

A seção Skill da página de desenvolvedores do Pensieve, explicando onde salvar o SKILL.md no Claude Code, no app do Claude e em outros agentes, ao lado de um terminal com os comandos de instalação

No app do Claude, a pasta com o arquivo vai em Configurações › Capacidades. Em outros agentes, dá para colar o conteúdo do skill.md nas instruções do sistema. E se você quiser entender como se escreve uma Skill dessas para a sua própria API, eu contei o passo a passo em Criando uma Skill para IAs usarem a sua API. 🪄

🔌 O MCP: a IA ganha ferramentas

A Skill ensina a IA a chamar a API. O MCP (Model Context Protocol) vai por outro caminho: o Pensieve é um servidor que entrega à IA ferramentas prontas, cada uma com nome, descrição e parâmetros. A IA não monta curl nenhum: ela chama create_note e pronto.

O servidor fica em https://www.pensieve.com.br/api/mcp. No Claude, no ChatGPT, no Cursor ou no VS Code, você adiciona esse endereço como conector personalizado, e abre uma janela do Pensieve para você entrar e autorizar (OAuth 2.1 com PKCE). Repare: não precisa copiar chave nenhuma. As IAs conectadas aparecem em Minha conta › API, onde dá para desconectar cada uma.

No Claude Code, é um comando:

claude mcp add --transport http pensieve https://www.pensieve.com.br/api/mcp

Para cliente que não fala OAuth, dá para mandar a chave no cabeçalho, num mcp.json:

{
    "mcpServers": {
        "pensieve": {
            "type": "http",
            "url": "https://www.pensieve.com.br/api/mcp",
            "headers": {
                "Authorization": "Bearer SUA_CHAVE_AQUI"
            }
        }
    }
}
A seção Servidor MCP da página de desenvolvedores do Pensieve, com o endereço do servidor, o comando claude mcp add e a grade de ferramentas: search, fetch, whoami, list_notes, get_note_counts, create_note, create_notes, update_note, snooze_note, delete_note, restore_note, list_lists, create_list e update_list

Pedi ao servidor a lista de ferramentas (o método tools/list do protocolo) e vieram quinze:

FerramentaO que faz
searchBusca notas pelo texto
fetchLê uma nota pelo id
whoamiNome e e-mail da conta conectada
list_notesLista notas com filtros e paginação
get_note_countsContagens: todas, favoritas, com lembrete, sem lista, arquivadas e lixeira
create_noteCria uma nota, com lembrete e repetição se quiser
create_notesCria de 1 a 50 notas numa chamada
update_noteAltera ou arquiva uma nota
snooze_noteAdia o lembrete
delete_noteManda para a lixeira
restore_noteTira da lixeira
list_listsTodas as listas, na ordem da pessoa
create_listCria uma lista
update_listRenomeia ou muda a cor
delete_listExclui a lista; as notas ficam "Sem lista"

Vêm também três prompts prontos: organizar_sem_lista (sugere uma lista para cada nota solta e move depois da sua confirmação), resumo_da_semana (notas dos últimos 7 dias e lembretes dos próximos 7) e conversa_em_notas (tira as decisões e tarefas da conversa e salva como notas).

O MCP em ação

Com o conector ligado no Claude, o pedido "me lembra de tomar a poção de ânimo todo dia às 8h, por uma semana" virou uma chamada à create_note com estes argumentos:

{
    "content": "Tomar a poção de ânimo",
    "listId": 4,
    "remindAt": "2026-09-28T08:00:00-03:00",
    "repeat": {
        "freq": "daily",
        "count": 7
    },
    "timeZone": "America/Sao_Paulo"
}

O "por uma semana" virou count: 7, e a data veio com fuso, do jeito que a API exige. A resposta:

{
    "note": {
        "id": 24,
        "content": "Tomar a poção de ânimo",
        "listId": 4,
        "isFavorite": false,
        "isArchived": false,
        "archivedAt": null,
        "remindAt": "2026-09-28T11:00:00.000Z",
        "repeat": {
            "freq": "daily",
            "interval": 1,
            "count": 7
        },
        "createdAt": "2026-09-26T01:36:55.000Z",
        "updatedAt": "2026-09-26T01:36:55.000Z",
        "deletedAt": null,
        "purgeAt": null,
        "url": "https://www.pensieve.com.br/app?nota=24"
    }
}

É a mesma nota da API REST, com um campo a mais no fim: a url. Ela abre a nota direto no mural, e é por isso que a IA consegue responder "anotei, está aqui" com um link clicável. ✨

E a search devolve um formato mais enxuto, só com id, título e link. Buscando por "coruja":

{
    "results": [
        {
            "id": "23",
            "title": "Levar a coruja ao veterinário",
            "url": "https://www.pensieve.com.br/app?nota=23"
        },
        {
            "id": "17",
            "title": "Alimentar a coruja",
            "url": "https://www.pensieve.com.br/app?nota=17"
        }
    ]
}

Para ler a nota inteira, a IA chama a fetch com o id. E se você quer ver como é construir um MCP desses por dentro, com a ponte de OAuth, eu escrevi sobre isso em Criando um MCP para uma API com OAuth.

🎁 E o que mais vem junto

Fora a parte de IA, o Pensieve tem umas coisas que eu faço questão de mencionar, porque são justamente as que costumam ser pagas por aí:

  • Exportação em JSON, Markdown ou CSV, com listas, lembretes e repetições. Suas notas saem com você.
  • App para Windows, Mac e Linux, com notificação nativa e botão "Adiar 10 min".
  • Site instalável como app no celular e no computador, direto do navegador.
  • Arquivo e lixeira de 30 dias, com desfazer.
  • Atalhos de teclado: N escreve, / busca, F favorita.

Tudo isso, e a API, a Skill e o MCP, está em qualquer conta, de graça. A página com toda a parte técnica é esta:

Pensieve para desenvolvedoresAPI REST, documentação OpenAPI, Skill para agentes e servidor MCP do Pensieve.pensieve.com.br

Por hoje é só, meus unicórnios! 🦄✨

Que a magia do arco-íris continue brilhando em suas vidas! Até mais! 🌈🌟

Perguntas frequentes

O Pensieve é gratuito?
É. Não existe plano pago: notas, lembretes, app para computador, API, Skill e conector MCP estão liberados em toda conta. Os limites são técnicos e iguais para todos, como 120 requisições por minuto por chave.
Por que a API responde 422 "Data/hora inválida"?
Quase sempre porque o remindAt foi enviado sem fuso, como 2026-09-28T09:00:00. A API exige ISO 8601 com fuso: 2026-09-28T09:00:00-03:00 ou com Z no fim.
Por que o lembrete volta com um horário diferente do que eu mandei?
Porque as respostas vêm sempre em UTC. Um lembrete para as 9h de Brasília volta como 12:00:00.000Z. É o mesmo instante: converta para o fuso da pessoa na hora de mostrar.
Qual a diferença entre a Skill e o MCP do Pensieve?
A Skill é um Markdown que ensina a IA a chamar a API REST sozinha, usando a sua chave numa variável de ambiente. Serve para agentes que rodam comandos, como o Claude Code. O MCP é um servidor com ferramentas prontas (create_note, search e outras) que o Claude, o ChatGPT e o Cursor conectam com login OAuth, sem copiar chave.
Excluir uma nota pela API apaga de vez?
Não. O DELETE /notes/{id} manda a nota para a lixeira, de onde ela volta com POST /notes/{id}/restore por até 30 dias. Apagar de vez é o DELETE /notes/{id}/permanent, que só funciona com a nota já na lixeira.
Por que o acento da minha nota virou um ponto de interrogação?
No Git Bash do Windows, o JSON escrito direto no -d do curl chegou sem UTF-8, e "feitiços" virou "feiti�os". Grave o JSON num arquivo e envie com --data-binary @nota.json, ou use um script em Node.

Leia também