Ulule MCP
Creación de tu proyecto de financiación participativa
Servidor MCP alojado
npx add-mcp 'https://api.ulule.com/mcp/public'Se instala en Claude Code, Codex, Cursor y más
Documentación
Ulule MCP
Ulule expone un servidor público MCP (Model Context Protocol). Permite que un cliente MCP — como Claude, Cursor o cualquier asistente compatible con OAuth 2.1 — actúe en nombre de un usuario de Ulule: redactar una propuesta de proyecto, editar uno de los proyectos del usuario, fijar su objetivo de financiación, añadir imágenes y recompensas, o escribir una actualización de noticias, todo desde una conversación.
El endpoint del servidor es:
post https://api.ulule.com/mcp/public
Habla MCP sobre Streamable HTTP (se aceptan tanto POST como GET) y es sin estado: cada solicitud se autentica por sí misma, por lo que no hay una sesión de larga duración que mantener. Es una superficie distinta de la API REST de Ulule: endpoint diferente, autenticación diferente y un pequeño conjunto de herramientas con ámbito de usuario en lugar del árbol completo de recursos REST.
En nombre de quién actúa
Cada herramienta actúa solo para el usuario que posee el token de acceso. La identidad siempre proviene del token — nunca se pasa un id de usuario como argumento. Como consecuencia, un id (una propuesta o un proyecto) que no pertenezca al usuario autenticado se reporta como no encontrado, nunca como prohibido, por lo que el servidor no puede usarse para sondear qué ids existen.
Cómo conectarse
- Apunta tu cliente MCP a
https://api.ulule.com/mcp/public. - El cliente descubre el servidor de autorización y recorre el flujo OAuth 2.1 — ver Conexión. La mayoría de los clientes lo hacen automáticamente; el usuario solo ve la pantalla de consentimiento de Ulule.
- Una vez autorizado, el cliente puede llamar a las herramientas.
Conexión
El servidor MCP está protegido por OAuth 2.1. El acceso es por usuario final: el cliente obtiene un token de acceso para la persona que lo usa, y ese token es en nombre de quien actúa cada herramienta.
A diferencia del método OAuth2 utilizado por la API REST, no necesitas una aplicación de socio pre-registrada: el servidor MCP admite registro dinámico de clientes y PKCE, que casi todos los clientes MCP realizan automáticamente. En la práctica, el usuario solo ve la pantalla de autorización de Ulule.
Descubrimiento
Una solicitud no autenticada al endpoint MCP devuelve 401 con un encabezado WWW-Authenticate que apunta al documento de metadatos del recurso protegido (RFC 9728):
get https://api.ulule.com/.well-known/oauth-protected-resource
Ese documento nombra el recurso (https://api.ulule.com/mcp/public) y el servidor de autorización, cuyos propios metadatos (RFC 8414) se sirven en:
get https://api.ulule.com/.well-known/oauth-authorization-server
Un cliente MCP lee estos dos documentos por sí mismo para encontrar los endpoints a continuación.
Endpoints
| Paso | Endpoint |
|---|---|
| Registrar un cliente (RFC 7591) | POST https://api.ulule.com/oauth2/register/ |
| Autorizar (pantalla de consentimiento del usuario) | GET https://www.ulule.com/oauth2/authorize/ |
| Intercambiar el código / renovar el token | POST https://api.ulule.com/oauth2/token/ |
| Revocar un token | POST https://api.ulule.com/oauth2/revoke/ |
El flujo utiliza el grant authorization_code con PKCE (S256), y refresh_token para renovar un token de acceso caducado.
Uso del token
Envía el token de acceso en el encabezado Authorization, y en ningún otro lugar — un token pasado como parámetro de cadena de consulta se rechaza:
$ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" "https://api.ulule.com/mcp/public"
Límite de velocidad
Las llamadas tienen un límite de velocidad por usuario. Cuando se supera el límite, el servidor responde 429 Too Many Requests con un encabezado Retry-After; X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset se devuelven en cada respuesta para que un cliente pueda ajustar su ritmo.
Herramientas
Las herramientas que expone el servidor MCP público. Todas actúan solo para el usuario autenticado. Los campos multilingües (name, description, title, content) son objetos claveados por código de idioma, p. ej. {"fr": "Le Semainier"}, no cadenas simples.
ping
Comprueba que la conexión está autenticada y funciona. No toma argumentos y no devuelve datos sobre el usuario o sus proyectos. Útil para confirmar que un cliente está correctamente conectado antes de hacer cualquier otra cosa.
create_proposal
Envía una propuesta de proyecto de crowdfunding (en francés, proposition de collecte) en nombre del usuario. Es el primer paso para crear una campaña — no el proyecto en sí.
Solo se requieren country y description, por lo que una propuesta puede iniciarse ahora y completarse más tarde con update_proposal. Una propuesta está completa una vez que tiene país, moneda, idioma, descripción, un objetivo de financiación y recompensas; el campo submitted de la respuesta es false mientras sigue siendo un borrador incompleto y true una vez completa. Una propuesta completa se procesa automáticamente y no es revisada por un humano de inmediato. Si se acepta, se crea un proyecto a partir de ella como borrador no publicado: el propietario ya puede empezar a completarlo y ponerse en contacto con un coach, que modera el proyecto antes de que pueda publicarse. El id de ese proyecto aparece entonces como project_id en list_my_proposals — el identificador para las herramientas con ámbito de proyecto.
Llama a
list_my_proposalsprimero: si ya hay una propuesta abierta, actualízala en lugar de crear una segunda.
| Parámetro | Obligatorio | Descripción |
|---|---|---|
country | sí | Código de país ISO 3166-1 alpha-2, p. ej. FR. |
description | sí | Qué es el proyecto — lo que un coach lee primero. |
name | Título del proyecto. | |
type | Uno de project, presale, membership. Por defecto project. | |
currency | Código de moneda ISO 4217, p. ej. EUR. | |
lang | Idioma del proyecto, p. ej. fr. | |
goal | Objetivo de financiación en la moneda elegida (para type=project). | |
goal_range | Objetivo de financiación como horquilla {min, max} cuando no se fija una cifra exacta. | |
nb_products_min | Número mínimo de unidades a vender. Obligatorio cuando type=presale. | |
rewards | Qué reciben los mecenas, en prosa. | |
rewards_type | concrete, symbolic, financial, none o undefined. | |
city | Ciudad donde se basa el proyecto. | |
community_range | Audiencia a la que ya llega el remitente, como horquilla {min, max}. | |
date_start_estimation | Cuándo planea lanzar el remitente. | |
legal_entity_type | Forma jurídica del titular del proyecto. | |
structure | Empresa o asociación detrás del proyecto. | |
links | URLs del proyecto o de la audiencia existente del remitente. | |
phone_number | Número de teléfono de contacto (15 caracteres como máximo). | |
references | Cualquier otra cosa que el remitente quiera que sepan los coaches. |
update_proposal
Actualiza una de las propuestas del usuario. Solo se cambian los campos que pasas; todo lo demás se deja intacto. Una vez que no falta nada, la propuesta se vuelve completa y se procesa automáticamente — no hay un paso de envío separado, y no es revisada por un humano de inmediato. Una propuesta ya aceptada ya no se puede editar: se ha convertido en un proyecto, cuyo id aparece como project_id en list_my_proposals. Una vez aceptada, el propietario puede empezar a completar ese proyecto y ponerse en contacto con un coach.
| Parámetro | Obligatorio | Descripción |
|---|---|---|
proposal_id | sí | Id de la propuesta a actualizar, tal como lo devuelve create_proposal o list_my_proposals. |
| otros | Mismos campos que create_proposal (excepto city y community_range), cada uno opcional — un parche. |
list_my_proposals
Lista las propuestas del usuario. No toma argumentos. Cada entrada lleva el id necesario para actualizarla, si está completa y ha sido procesada (submitted; una propuesta aún no enviada sigue siendo un borrador incompleto), y — una vez que una propuesta se acepta y se convierte en proyecto — el project_id que toman las herramientas con ámbito de proyecto.
update_project
Reescribe el título o la descripción de uno de los proyectos del usuario. Solo se cambian los campos que pasas, y ninguno puede vaciarse.
Esta herramienta no puede cambiar la imagen, el objetivo de financiación, las fechas, las recompensas o el estado. Para eso, la respuesta devuelve enlaces backoffice para enviar al usuario.
| Parámetro | Obligatorio | Descripción |
|---|---|---|
project_id | sí | Id del proyecto (no se acepta un slug). |
name | Título del proyecto, claveado por código de idioma, p. ej. {"fr": "Le Semainier"}. | |
description | Descripción del proyecto (se permite HTML), claveada por código de idioma. |
Debe proporcionarse al menos uno de name o description.
update_goal
Establece el tipo y el objetivo de financiación de uno de los proyectos del usuario. Solo se cambian los campos que pasas.
Cambiar el tipo solo es posible mientras el proyecto sigue siendo un borrador, y el objetivo ya no se puede cambiar una vez que la campaña está terminando. Cuando el estado del proyecto prohíbe el cambio, la herramienta responde con el motivo.
| Parámetro | Obligatorio | Descripción |
|---|---|---|
project_id | sí | Id del proyecto (no se acepta un slug). |
type | presale (campaña de preventa) o project (recaudación todo o nada). | |
goal | Objetivo de financiación como importe entero en la moneda del proyecto, p. ej. 5000. Debe ser positivo. |
Debe proporcionarse al menos uno de type o goal.
create_project_image
Añade una imagen a uno de los proyectos del usuario. Los bytes se dan codificados en base64 (image_base64) o como una URL pública http(s) (image_url) — exactamente una de las dos. Los formatos aceptados son png, jpeg y gif, hasta 5.5 MB. Una URL obtenida debe ser públicamente accesible y no se sigue a través de redirecciones.
El type elige el rol de la imagen:
main— la imagen principal de la campaña, mostrada en la parte superior de la página pública del proyecto (al menos 640×360). Una por idioma.background— la imagen de fondo de la página (al menos 1440×530). Una por idioma.secondary— una imagen adicional guardada en la biblioteca de medios del proyecto. Se almacena pero no se muestra en la página pública por sí sola; para mostrarla, toma elurlque devuelve esta herramienta e insértalo en la descripción del proyecto conupdate_project.
main y background pueden establecerse cada una una vez por idioma y no se pueden reemplazar aquí — hazlo desde el back office. Esta herramienta nunca cambia el objetivo, las fechas, las recompensas o el estado.
| Parámetro | Obligatorio | Descripción |
|---|---|---|
project_id | sí | Id del proyecto (no se acepta un slug). |
type | sí | Uno de main, background, secondary. |
lang | sí | Código de idioma para el que se establece la imagen, p. ej. fr. |
image_base64 | Los bytes de la imagen, codificados en base64. Se acepta un prefijo de URI data:. Da esto o image_url, no ambos. | |
image_url | URL pública http(s) para obtener la imagen. Da esto o image_base64, no ambos. |
La respuesta devuelve el id, type, lang de la imagen almacenada y (excepto para un fondo) su url.
create_reward
Añade una recompensa (contrepartie) a uno de los proyectos del usuario: su título, descripción, precio y, opcionalmente, una imagen.
Una imagen es opcional. Cuando se da, se proporciona codificada en base64 (image_base64) o como una URL pública http(s) (image_url) — como máximo una de las dos — y se convierte en la imagen de la recompensa. Se acepta cualquier tamaño (png, jpeg o gif, hasta 5.5 MB); a diferencia de la imagen main o background de un proyecto, una imagen de recompensa no tiene dimensiones mínimas.
Esta herramienta no puede establecer el stock, variantes, opciones, envío o configuración de impuestos. Para eso, la respuesta devuelve un backoffice_url para enviar al usuario.
| Parámetro | Obligatorio | Descripción |
|---|---|---|
project_id | sí | Id del proyecto (no se acepta un slug). |
title | sí | Título de la recompensa, organizado por código de idioma, p. ej. {"fr": "Un tote bag"}. Debe incluir el idioma principal del proyecto. |
price | sí | Precio que paga un patrocinador por la recompensa, en la moneda del proyecto, p. ej. 25 para 25.00. Debe ser al menos 1. |
description | Descripción de la recompensa (se permite HTML), organizada por código de idioma. | |
image_base64 | Imagen de la recompensa, codificada en base64. Se acepta un prefijo de URI data:. Proporcione esto o image_url, no ambos. | |
image_url | URL pública http(s) para obtener la imagen de la recompensa. Proporcione esto o image_base64, no ambos. |
create_news
Escribe una actualización de noticias en uno de los proyectos del usuario. La noticia se guarda como borrador y no se envía nada: no sale ningún correo electrónico hasta que el usuario la publique él mismo desde el back office del proyecto. Esta herramienta no puede publicar, programar ni adjuntar una imagen o un video.
| Parámetro | Obligatorio | Descripción |
|---|---|---|
project_id | sí | Id del proyecto en el que publicar la noticia. |
title | sí | Título de la noticia, organizado por código de idioma. Se requiere el idioma propio del proyecto. |
content | sí | Cuerpo de la noticia (se permite HTML), organizado por código de idioma. Se requiere el idioma propio del proyecto. |
audience_type | Para quién es la noticia: all, supporters, fans, paying-members o tip-supporters. El valor predeterminado es all. |