Fresh Jots MCP Server
Servidor MCP FreshJotsDotCom
Documentação
REST com token Bearer. Apenas notas de texto simples. Disponível nos planos Dev e Team. Para a apresentação sistêmica — cada script tem seu próprio caderno, anexação por nome de arquivo para jobs cron e resumos de sessões de IA, fluxos de trabalho do mundo real — veja /for/developers. URL base: https://freshjots.com/api/v1
Referência rápida — clientes
Linux e macOS
Windows e JS
Gem Ruby
Exemplos rápidos de uso da API. Exemplos curl prontos para copiar para os fluxos de trabalho comuns: criar, logs somente-anexação, anexar por nome de arquivo, listar.
Trabalhando com pastas? Crie pastas, coloque notas nelas na criação, envio em massa para uma pasta.
No Windows, ou prefere não instalar? Escreva na sua conta via PowerShell sem instalação, ou com o cliente npm / pip — sem precisar de WSL.
Autenticação
Gere um token pessoal em /settings/api_tokens. Os tokens são exibidos apenas uma vez na criação e armazenados como hash de via única — copie para o seu gerenciador de senhas ou perfil do shell imediatamente.
Authorization: Bearer mn_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Token ausente ou inválido retorna 401 unauthenticated. Titular do token sem acesso à API (plano Free / Personal) retorna 403 forbidden.
Escopos. Cada token é emitido com um nível de permissão — read_write (acesso total, o padrão), read_only (somente GET / HEAD) ou write_only (somente POST / PATCH / PUT / DELETE). Um token também pode ser bloqueado para uma única nota, para que possa ler ou anexar exatamente a esse fluxo e nada mais — útil como credencial por script. Uma solicitação fora do escopo do token retorna 403 forbidden com uma mensagem nomeando a restrição. Escolha o escopo ao criar o token.
Tokens de equipe
Workspaces no plano Team emitem tokens em /team/api_tokens (somente proprietário / administrador). Mesmo formato de fio do token Bearer, mesmos endpoints, mesmo envelope de erro — mas cada leitura e escrita resolve para as notas, pastas e pool de armazenamento da equipe, em vez do pool pessoal do ator.
GET /noteslista apenas as notas da equipe; as notas pessoais do ator nunca aparecem.POST /notescria comteam_iddefinido; ouser_idda linha registra o ator (quem escreveu) para o log de auditoria em /team/audit_events./folders/*,/notes/bulke/notes/:id/movesão sensíveis a escopo — um token de equipe só vê as pastas da equipe, nunca as pessoais, e recusa colocação entre pools com404 not_found.- Armazenamento, limites de taxa e limites por nível vêm da assinatura da equipe, não do ator. O envio em massa é habilitado em todo token de equipe — a assinatura da equipe é o direito.
O limite de tokens ativos de uma equipe é de 30 tokens ativos por vez. A revogação fica no mesmo painel — tokens revogados permanecem listados para auditoria, mas param de autenticar imediatamente.
Endpoints
| Método | Caminho | Finalidade |
|---|---|---|
| GET | /notes | Listar notas (resumo). Filtrar por ?format=plain|rich, ?folder_id=N (ou none para sem pasta). Ordenar por ?sort=created|updated|appended (padrão: atualizado). Paginar com ?limit=N&offset=N (máx. 200/página). |
| GET | /notes/:id | Nota completa (plain_body + byte_size). |
| POST | /notes | Criar nota de texto simples. Corpo: {note: {title, plain_body, folder_id?, append_only?, client_encrypted?}}. client_encrypted: true armazena uma nota que você criptografou localmente com sua própria chave — mantida literalmente, nunca lida ou indexada (somente contas pessoais; imutável após a criação). |
| PATCH | /notes/:id | Atualizar título / plain_body / configurações. O formato é imutável. Em notas somente-anexação, campos de conteúdo são recusados, mas configurações (folder_id, append_deadline_hours, alert_email, webhook_url, webhook_secret) são aceitas. |
| DELETE | /notes/:id | Excluir nota. |
| POST | /notes/:id/append | Anexação atômica a plain_body. Corpo: {text}. |
| POST | /notes/:id/move | Mover para pasta. Corpo: {folder_id} ou null. |
| GET | /notes/by-filename/:filename | Encontrar por nome de arquivo em vez de id. |
| PATCH | /notes/by-filename/:filename | Mesma forma de corpo que PATCH /notes/:id, endereçada pelo nome do fluxo. Útil para reconfigurar a nota de um script (prazo, URL de webhook) sem primeiro procurar o id. |
| POST | /notes/by-filename/:filename/append | Endereçamento de fluxo — anexar por nome de arquivo. Cria a nota se ausente (somente-anexação por padrão). No primeiro toque, client_encrypted: true a abre como fluxo criptografado pelo cliente — envie uma linha de ciphertext autocontida por anexação (somente contas pessoais). Ignorado quando a nota já existe. |
| POST | /notes/bulk | Até 50 criações por chamada. Corpo: {notes: [...]}. |
| GET | /folders | Listar pastas. |
| GET | /folders/:id | Mostrar uma única pasta. |
| POST | /folders | Criar pasta. Corpo: {folder: {name}}. |
| PATCH | /folders/:id | Renomear pasta. |
| DELETE | /folders/:id | Excluir pasta. As notas dentro são preservadas (sem pasta). |
Limites de taxa
- Dev: 600 leituras / 60 escritas / 300 anexações por minuto, por token. 3 tokens ativos. 15 GB de armazenamento. Endpoint em massa habilitado.
- Team: 2.000 leituras / 200 escritas / 1.000 anexações por minuto, por token. 30 tokens ativos por equipe. 50 GB de armazenamento do workspace. Endpoint em massa habilitado. 50.000 notas de texto simples / 1.000 notas ricas por equipe.
Solicitações limitadas retornam 429 rate_limited com os cabeçalhos Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset.
A divisão completa por nível — incluindo limites de tamanho por nota, limites de superfície do navegador, tetos de paginação, política de expiração de token e a janela de exportação — está na página Service limits.
Repetições idempotentes
Todo endpoint de escrita (POST, PATCH, PUT, DELETE) aceita um cabeçalho de solicitação Idempotency-Key. Uma solicitação repetida com a mesma chave + mesma impressão digital de corpo reproduz a resposta original em vez de executar a ação duas vezes — seguro para repetições de "a solicitação anterior foi bem-sucedida antes do meu timeout?" em jobs cron e scripts de CI.
- Cabeçalho:
Idempotency-Key: <your-key> - Formato da chave: 8..255 caracteres. UUIDs funcionam; qualquer string nesse intervalo também.
- Janela de repetição: 24 horas. Depois disso, a mesma chave é aceita como uma nova solicitação.
- Repetições carregam
Idempotent-Replay: truena resposta para que seu cliente possa identificar.
Uma chave repetida com uma impressão digital de corpo diferente retorna 409 idempotency_key_conflict — o servidor se recusa a sobrescrever silenciosamente a resposta de uma solicitação anterior. Repita com o corpo original ou gere uma nova chave.
curl -X POST https://freshjots.com/api/v1/notes \
-H "Authorization: Bearer $FRESH_JOTS_TOKEN" \
-H "Idempotency-Key: cron-2026-05-06-evening-digest" \
-H "Content-Type: application/json" \
-d '{"note":{"title":"Evening digest","plain_body":"...","format":"plain"}}'
Envelope de erro
Todas as respostas de erro compartilham a mesma forma:
{ "error": { "code": "validation_failed", "message": "Title can't be blank", "details": ["Title can't be blank"] } }
Códigos de erro estáveis:
unauthenticated— token ausente / inválido (401)forbidden— token sem acesso à API, fora do escopo ou conta não confirmada (403)note_locked— atualização ou exclusão tentada em nota somente-anexação; apenas mais anexações são permitidas (403)not_found— registro ausente ou pertencente a outro usuário (404)validation_failed— entrada inválida ou violação de esquema (422)cap_exceeded— contagem de notas acima do limite do seu nível (422)storage_cap_exceeded— total de bytes excederia seu limite de armazenamento (422)content_too_large— nota única acima do limite de bytes por formato (413)content_type_mismatch— tentativa de escrita de nota rica via API (422)rate_limited— janela de limitação excedida (429)idempotency_key_conflict— chave de repetição reutilizada com corpo diferente (409). Veja Repetições idempotentes acima.service_unavailable— backend temporariamente inacessível; seguro repetir com backoff (503)
Watchdog e webhooks
Dois controles por nota para transformar um fluxo em substrato de monitoramento. Ambos são configurados via PATCH /notes/:id (ou PATCH /notes/by-filename/:filename) e também podem ser definidos na página de Configurações por nota na interface web. Ambos exigem que a nota seja somente-anexação; o sinalizador subjacente é definido na criação ({"append_only": true}) ou pelo alternador de bloqueio no navegador.
Alertas de interruptor de homem morto
Defina append_deadline_hours em uma nota somente-anexação (1–720) e o Fresh Jots envia um e-mail quando nenhuma anexação chega nessa janela. A próxima anexação limpa o alerta; se o script se recuperar e falhar novamente, você recebe um novo e-mail — sem redefinição manual. alert_email opcional substitui o destino (padrão: e-mail da sua conta).
curl -X PATCH https://freshjots.com/api/v1/notes/by-filename/cron-jobs-prod \
-H "Authorization: Bearer $FRESHJOTS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"note":{"append_deadline_hours":2,"alert_email":"oncall@example.com"}}'
Webhooks de saída
Defina webhook_url em uma nota somente-anexação e cada anexação bem-sucedida faz POST do novo conteúdo para seu endpoint. Por padrão, o corpo é um envelope JSON assinado — HMAC-SHA256 no cabeçalho X-FreshJots-Signature (formato: sha256=<hex>) usando o webhook_secret que você configura; um segredo em branco assina com a string vazia, e o segredo nunca é lido de volta via API. Defina webhook_format como slack ou discord para enviar uma mensagem de chat nativa (veja "Formatos de payload" abaixo).
Dez respostas não-2xx consecutivas (ou falhas de transporte) desativam automaticamente o webhook para que um receptor morto não drene a fila de jobs. Reative-o salvando a nota novamente — seja com uma nova URL ou, após desativação automática, com a URL inalterada (o salvamento deliberado é o reconhecimento). webhook_failure_count e webhook_disabled_at são expostos em GET /notes/:id para monitoramento.
curl -X PATCH https://freshjots.com/api/v1/notes/by-filename/payments-prod \
-H "Authorization: Bearer $FRESHJOTS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"note":{"webhook_url":"https://hooks.example.com/x","webhook_secret":"sk_..."}}'
Forma do payload:
{
"event": "note.appended",
"delivered_at": "2026-05-02T12:34:56Z",
"delivery_id": "<uuid>",
"note": {
"id": 123, "filename": "payments-prod", "title": "payments-prod",
"byte_size": 4096, "last_appended_at": "2026-05-02T12:34:55Z"
},
"appended_text": "...new chunk (capped at 8 KB)...",
"appended_bytes": 42,
"appended_truncated": false
}
Formatos de payload
webhook_format controla a forma do payload e aceita três valores: generic (padrão — o envelope note.appended assinado mostrado acima, para seu próprio servidor ou um hub de automação como Zapier / Make / n8n); slack (uma mensagem de chat nativa do Slack — cole uma URL https://hooks.slack.com/services/... e pronto, sem adaptador para escrever); e discord (a mesma ideia para URLs https://discord.com/api/webhooks/...). Defina pelo menu suspenso da página de Configurações ou pelo mesmo endpoint PATCH que aceita webhook_url / webhook_secret; o valor atual volta em cada GET /notes/:id. Uma nota sem definição usa o padrão generic.
Mensagens em formato de chat são truncadas para caber em cada plataforma: Slack para 3.500 caracteres, Discord para 1.900 caracteres sob o teto rígido de 2.000 caracteres do Discord no campo content. A prévia Genérica appended_text permanece inalterada (limitada a 8 KB; o corpo completo é sempre acessível via GET /notes/:id).
Entregas do Slack e Discord não são assinadas. Os webhooks de entrada de nenhuma das plataformas podem verificar uma assinatura, então o cabeçalho X-FreshJots-Signature é omitido completamente. Para esses formatos, a URL de hook impossível de adivinhar é a credencial; trate-a como senha. As regras de assinatura em "Verificando entregas" abaixo se aplicam apenas ao formato Genérico.
curl -X PATCH https://freshjots.com/api/v1/notes/by-filename/cron-jobs-prod \
-H "Authorization: Bearer $FRESHJOTS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"note":{"webhook_url":"https://hooks.slack.com/services/T.../B.../...","webhook_format":"slack"}}'
Verificando entregas (somente Genérico)
Seu endpoint é uma URL pública, então verifique cada entrega antes de confiar nela. Defina o mesmo webhook_secret no seu servidor receptor, recalcule o HMAC sobre o corpo da solicitação bruto, não analisado, e compare com o cabeçalho X-FreshJots-Signature usando uma comparação de tempo constante. Rejeite em caso de incompatibilidade antes de analisar o JSON. (Se você configurou um segredo em branco, a chave é a string vazia.)
require "openssl"
require "active_support/security_utils"
SECRET = ENV.fetch("FRESHJOTS_WEBHOOK_SECRET") # the same value you set on the note
def verified?(raw_body, header)
expected = "sha256=#{OpenSSL::HMAC.hexdigest("SHA256", SECRET, raw_body)}"
header.to_s.bytesize == expected.bytesize &&
ActiveSupport::SecurityUtils.secure_compare(header.to_s, expected)
end
# Rails: verify request.raw_post (NOT params) against
# request.headers["X-FreshJots-Signature"], then head(:unauthorized) on false.
Atualizações ao vivo no navegador
Aviso: quando você tem uma nota aberta na interface web e uma escrita via API a atinge, apenas notas somente-anexação atualizam no lugar — o navegador assina um fluxo por usuário e substitui o corpo conforme novo conteúdo chega, sem precisar atualizar. Experimente: abra uma nota somente-anexação em uma aba e depois curl uma anexação de outra janela.
Notas editáveis (CRUD) atualizadas via API (PATCH /api/v1/notes/:id, POST /notes/:id/append em uma nota não bloqueada) não são enviadas para uma aba aberta no navegador — atualize a página para obter o novo conteúdo. Isso é por design: empurrar trocas de conteúdo no meio da edição colidiria com o autosave em andamento do editor.
Dúvidas? Fale comigo diretamente.