Ulule MCP

Criação do seu projeto de financiamento coletivo

Servidor MCP hospedado

npx add-mcp 'https://api.ulule.com/mcp/public'

Instala no Claude Code, Codex, Cursor e outros

Documentação

Ulule MCP

O Ulule expõe um servidor público MCP (Model Context Protocol). Ele permite que um cliente MCP — como Claude, Cursor ou qualquer assistente compatível com OAuth 2.1 — atue em nome de um usuário do Ulule: redigir uma proposta de projeto, editar um dos projetos do usuário, definir sua meta de financiamento, adicionar imagens e recompensas ou escrever uma atualização de notícias, tudo a partir de uma conversa.

O endpoint do servidor é:

post https://api.ulule.com/mcp/public

Ele fala MCP sobre Streamable HTTP (tanto POST quanto GET são aceitos) e é stateless: cada requisição é autenticada individualmente, portanto não há sessão de longa duração para manter ativa. É uma superfície distinta da API REST do Ulule: endpoint diferente, autenticação diferente e um pequeno conjunto de ferramentas com escopo de usuário, em vez da árvore completa de recursos REST.

Em nome de quem atua

Cada ferramenta atua apenas para o usuário que possui o token de acesso. A identidade sempre vem do token — você nunca passa um id de usuário como argumento. Como consequência, um id (uma proposta ou um projeto) que não pertence ao usuário autenticado é reportado como não encontrado, nunca como proibido, portanto o servidor não pode ser usado para sondar quais ids existem.

Conectando-se

  1. Aponte seu cliente MCP para https://api.ulule.com/mcp/public.
  2. O cliente descobre o servidor de autorização e percorre o fluxo OAuth 2.1 — veja Conectando. A maioria dos clientes faz isso automaticamente; o usuário apenas vê a tela de consentimento do Ulule.
  3. Uma vez autorizado, o cliente pode chamar as ferramentas.

Conectando

O servidor MCP é protegido por OAuth 2.1. O acesso é por usuário final: o cliente obtém um token de acesso para a pessoa que o utiliza, e é esse token que cada ferramenta usa para agir em nome do usuário.

Diferentemente do método OAuth2 usado pela API REST, você não precisa de um aplicativo de parceiro pré-registrado: o servidor MCP suporta registro dinâmico de cliente e PKCE, que quase todo cliente MCP realiza automaticamente. Na prática, o usuário apenas vê a tela de autorização do Ulule.

Descoberta

Uma requisição não autenticada ao endpoint MCP retorna 401 com um cabeçalho WWW-Authenticate apontando para o documento de metadados do recurso protegido (RFC 9728):

get https://api.ulule.com/.well-known/oauth-protected-resource

Esse documento nomeia o recurso (https://api.ulule.com/mcp/public) e o servidor de autorização, cujos próprios metadados (RFC 8414) são servidos em:

get https://api.ulule.com/.well-known/oauth-authorization-server

Um cliente MCP lê esses dois documentos por conta própria para encontrar os endpoints abaixo.

Endpoints

EtapaEndpoint
Registrar um cliente (RFC 7591)POST https://api.ulule.com/oauth2/register/
Autorizar (tela de consentimento do usuário)GET https://www.ulule.com/oauth2/authorize/
Trocar o código / renovar o tokenPOST https://api.ulule.com/oauth2/token/
Revogar um tokenPOST https://api.ulule.com/oauth2/revoke/

O fluxo usa a concessão authorization_code com PKCE (S256) e refresh_token para renovar um token de acesso expirado.

Usando o token

Envie o token de acesso no cabeçalho Authorization e em nenhum outro lugar — um token passado como parâmetro de query-string é rejeitado:

$ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" "https://api.ulule.com/mcp/public"

Limite de taxa

As chamadas são limitadas por usuário. Quando o limite é excedido, o servidor responde com 429 Too Many Requests e um cabeçalho Retry-After; X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset são retornados em cada resposta para que o cliente possa se ajustar.

Ferramentas

As ferramentas que o servidor MCP público expõe. Todas atuam apenas para o usuário autenticado. Campos multilíngues (name, description, title, content) são objetos indexados por código de idioma, ex.: {"fr": "Le Semainier"}, não strings simples.

ping

Verifica se a conexão está autenticada e funcionando. Não recebe argumentos e não retorna dados sobre o usuário ou seus projetos. Útil para confirmar que um cliente está corretamente conectado antes de fazer qualquer outra coisa.

create_proposal

Submete uma proposta de projeto de crowdfunding (em francês, proposition de collecte) em nome do usuário. É o primeiro passo para criar uma campanha — não o projeto em si.

Apenas country e description são obrigatórios, então uma proposta pode ser iniciada agora e concluída depois com update_proposal. Uma proposta está completa quando possui país, moeda, idioma, descrição, uma meta de financiamento e recompensas; o campo submitted da resposta é false enquanto ainda é um rascunho incompleto e true quando completa. Uma proposta completa é processada automaticamente e não é revisada por um humano imediatamente. Se for aceita, um projeto é criado a partir dela como um rascunho não publicado: o proprietário já pode começar a preenchê-lo e entrar em contato com um coach, que modera o projeto antes de ele poder ser publicado. O id desse projeto então aparece como project_id em list_my_proposals — o identificador para as ferramentas com escopo de projeto.

Chame list_my_proposals primeiro: se uma proposta já estiver aberta, atualize-a em vez de criar uma segunda.

ParâmetroObrigatórioDescrição
countrysimCódigo de país ISO 3166-1 alpha-2, ex.: FR.
descriptionsimO que é o projeto — o que um coach lê primeiro.
nameTítulo do projeto.
typeUm de project, presale, membership. Padrão: project.
currencyCódigo de moeda ISO 4217, ex.: EUR.
langIdioma do projeto, ex.: fr.
goalMeta de financiamento na moeda escolhida (para type=project).
goal_rangeMeta de financiamento como faixa {min, max} quando nenhum valor exato é definido.
nb_products_minNúmero mínimo de unidades a vender. Obrigatório quando type=presale.
rewardsO que os apoiadores recebem, em prosa.
rewards_typeconcrete, symbolic, financial, none ou undefined.
cityCidade onde o projeto está sediado.
community_rangePúblico que o submissor já alcança, como faixa {min, max}.
date_start_estimationQuando o submissor planeja lançar.
legal_entity_typeForma jurídica do titular do projeto.
structureEmpresa ou associação por trás do projeto.
linksURLs do projeto ou do público existente do submissor.
phone_numberNúmero de telefone para contato (no máximo 15 caracteres).
referencesQualquer outra coisa que o submissor queira que os coaches saibam.

update_proposal

Atualiza uma das propostas do usuário. Apenas os campos que você passar são alterados; todo o resto permanece intacto. Quando nada mais estiver faltando, a proposta se torna completa e é processada automaticamente — não há etapa separada de envio, e ela não é revisada por um humano imediatamente. Uma proposta já aceita não pode mais ser editada: ela se tornou um projeto, cujo id aparece como project_id em list_my_proposals. Uma vez aceita, o proprietário pode começar a preencher esse projeto e entrar em contato com um coach.

ParâmetroObrigatórioDescrição
proposal_idsimId da proposta a atualizar, conforme retornado por create_proposal ou list_my_proposals.
outrosMesmos campos de create_proposal (exceto city e community_range), cada um opcional — um patch.

list_my_proposals

Lista as propostas do usuário. Não recebe argumentos. Cada entrada traz o id necessário para atualizá-la, se está completa e foi processada (submitted; uma proposta ainda não enviada é um rascunho incompleto) e — uma vez que uma proposta é aceita e transformada em projeto — o project_id que as ferramentas com escopo de projeto recebem.

update_project

Reescreve o título ou a descrição de um dos projetos do usuário. Apenas os campos que você passar são alterados, e nenhum deles pode ser esvaziado.

Esta ferramenta não pode alterar a imagem, a meta de financiamento, as datas, as recompensas ou o status. Para esses casos, a resposta retorna links backoffice para enviar o usuário.

ParâmetroObrigatórioDescrição
project_idsimId do projeto (um slug não é aceito).
nameTítulo do projeto, indexado por código de idioma, ex.: {"fr": "Le Semainier"}.
descriptionDescrição do projeto (HTML permitido), indexada por código de idioma.

Pelo menos um de name ou description deve ser fornecido.

update_goal

Define o tipo e a meta de financiamento de um dos projetos do usuário. Apenas os campos que você passar são alterados.

Alterar o tipo só é possível enquanto o projeto ainda é um rascunho, e a meta não pode mais ser alterada quando a campanha está terminando. Quando o estado do projeto impede a alteração, a ferramenta responde com o motivo.

ParâmetroObrigatórioDescrição
project_idsimId do projeto (um slug não é aceito).
typepresale (campanha de pré-venda) ou project (arrecadação tudo-ou-nada).
goalMeta de financiamento como valor inteiro na moeda do projeto, ex.: 5000. Deve ser positivo.

Pelo menos um de type ou goal deve ser fornecido.

create_project_image

Adiciona uma imagem a um dos projetos do usuário. Os bytes são fornecidos codificados em base64 (image_base64) ou como uma URL http(s) pública (image_url) — exatamente um dos dois. Formatos aceitos: png, jpeg e gif, até 5,5 MB. Uma URL buscada deve ser publicamente acessível e não é seguida através de redirecionamentos.

O type escolhe o papel da imagem:

  • main — a imagem principal da campanha, exibida no topo da página pública do projeto (pelo menos 640×360). Uma por idioma.
  • background — a imagem de fundo da página (pelo menos 1440×530). Uma por idioma.
  • secondary — uma imagem extra mantida na biblioteca de mídia do projeto. Ela é armazenada, mas não exibida na página pública por conta própria; para mostrá-la, pegue o url que esta ferramenta retorna e incorpore-o na descrição do projeto com update_project.

main e background podem ser definidos uma vez por idioma e não podem ser substituídos aqui — faça isso no back office. Esta ferramenta nunca altera a meta, as datas, as recompensas ou o status.

ParâmetroObrigatórioDescrição
project_idsimId do projeto (um slug não é aceito).
typesimUm de main, background, secondary.
langsimCódigo de idioma para o qual a imagem é definida, ex.: fr.
image_base64Os bytes da imagem, codificados em base64. Um prefixo de URI data: é aceito. Forneça isto ou image_url, não ambos.
image_urlURL http(s) pública para buscar a imagem. Forneça isto ou image_base64, não ambos.

A resposta retorna o id, type, lang da imagem armazenada e (exceto para um fundo) seu url.

create_reward

Adiciona uma recompensa (contrepartie) a um dos projetos do usuário: seu título, descrição, preço e, opcionalmente, uma imagem.

Uma imagem é opcional. Quando fornecida, é dada codificada em base64 (image_base64) ou como uma URL http(s) pública (image_url) — no máximo uma das duas — e se torna a imagem da recompensa. Qualquer tamanho é aceito (png, jpeg ou gif, até 5,5 MB); diferentemente da imagem main ou background de um projeto, uma imagem de recompensa não tem dimensões mínimas.

Esta ferramenta não pode definir estoque, variantes, opções, frete ou configurações de impostos. Para esses casos, a resposta retorna um backoffice_url para enviar o usuário.

ParâmetroObrigatórioDescrição
project_idsimId do projeto (um slug não é aceito).
titlesimTítulo da recompensa, organizado por código de idioma, ex.: {"fr": "Un tote bag"}. Deve incluir o idioma principal do projeto.
pricesimPreço que um apoiador paga pela recompensa, na moeda do projeto, ex.: 25 para 25,00. Deve ser de pelo menos 1.
descriptionDescrição da recompensa (HTML permitido), organizada por código de idioma.
image_base64Imagem da recompensa, codificada em base64. Um prefixo de URI data: é aceito. Forneça ou image_url, não ambos.
image_urlURL pública http(s) para buscar a imagem da recompensa. Forneça ou image_base64, não ambos.

create_news

Escreva uma atualização de notícia em um dos projetos do usuário. A notícia é salva como rascunho e nada é enviado — nenhum e-mail é disparado até que o usuário a publique por conta própria no back office do projeto. Esta ferramenta não pode publicar, agendar ou anexar uma imagem ou um vídeo.

ParâmetroObrigatórioDescrição
project_idsimId do projeto no qual publicar a notícia.
titlesimTítulo da notícia, organizado por código de idioma. O idioma do próprio projeto é obrigatório.
contentsimCorpo da notícia (HTML permitido), organizado por código de idioma. O idioma do próprio projeto é obrigatório.
audience_typePara quem a notícia se destina: all, supporters, fans, paying-members ou tip-supporters. O padrão é all.