El servidor MCP de Campbooks está en POST /api/mcp en cualquier instancia de Campbooks. Implementa el protocolo MCP versión 2025-03-26 sobre HTTP streamable y expone 72 tools (más 3 tools de contexto que no requieren scope).
Autorización
POST /api/mcp acepta tres formas de Authorization:
| Forma | Valor de cabecera | Notas |
|---|
| Clave MCP | Bearer <uid>.<client-secret> | UID del cliente y secret en texto plano separados por un punto. Los UIDs y secrets de Doorkeeper no contienen puntos, así que el punto es inequívoco. |
| HTTP Basic | Basic base64(uid:secret) | Equivalente HTTP estándar de la forma de clave MCP. |
| Token Doorkeeper | Bearer <access-token> | Token de corta duración (2 h) obtenido en POST /api/oauth/token. Funciona para scripts puntuales; no adecuado para configuraciones estáticas de agentes. |
La REST API (/api/v1/*) acepta solo tokens bearer de Doorkeeper. Las formas 1 y 2 — claves MCP — solo están soportadas en /api/mcp.
Caducidad y rotación de claves
Las claves MCP no caducan. El servidor realiza una comparación bcrypt en cada petición; las tasas de llamada de agentes están bien dentro del límite de 600 req/min.
Revocar un token de acceso de Doorkeeper no desactiva una clave MCP. Para revocar una clave MCP, rota el client secret o elimina el cliente en Ajustes → Acceso a la API. La clave MCP se muestra una vez al crear el cliente; regenera el client secret si la pierdes.
Códigos de error de autenticación
| Estado | error.code | Cuándo |
|---|
| 401 | invalid_client | Cliente no encontrado, secret incorrecto, aplicación no confidencial o secret en blanco |
| 403 | insufficient_scope | El cliente no tiene scopes asignados |
Scopes
Los scopes controlan qué tools aparecen en tools/list. Un conjunto más restringido significa menos tools y menos contexto por sesión. La lista completa de scopes está documentada en la descripción general de la API en Desarrolladores.
Los tres tools de contexto — get_overview, get_setup_status y guide — no requieren scope y están siempre disponibles para cualquier cliente autenticado.
Límites de velocidad
600 peticiones por minuto por cliente. Superar el límite devuelve HTTP 429 con error.code: "rate_limit_exceeded".
Los tools están agrupados por familia a continuación. La columna "Scope" muestra el OAuth scope requerido; (any) significa que no se requiere scope.
Tools de contexto
| Tool | Scope | Finalidad |
|---|
get_overview | (any) | Snapshot rápido de lo que necesita atención. Devuelve solo las secciones cuyos recuentos no son cero. Llama a este primero. |
get_setup_status | (any) | Snapshot de configuración del espacio de trabajo para incorporación y diagnósticos. Lista lagunas como next_steps para guiar la skill de configuración. |
guide | (any) | Guías narrativas para trabajar con Campbooks via MCP. Sin tema — lista de temas disponibles. Pasa un nombre de tema para la guía completa. |
Correo electrónico
| Tool | Scope | Finalidad |
|---|
list_emails | emails:read | Lista los correos más recientes accesibles al llamador, del más reciente al más antiguo. Filtros opcionales: no leídos, consulta, cuenta, categoría, prioridad, rango de fechas. |
search_emails | emails:read | Busca correos con filtros. Usa una combinación semántica + por palabras clave cuando se da una consulta de texto. |
get_email | emails:read | Obtiene un único correo por id. format=text (predeterminado) devuelve el cuerpo en texto plano, truncado en 8 000 caracteres. |
send_email | emails:send | Envía un nuevo correo desde una de las cuentas conectadas del llamador. |
reply_email | emails:send | Responde a un correo existente. Encadena desde el mensaje fuente y envía desde su cuenta salvo que se sustituya. |
mark_email_read | emails:write | Marca un correo como leído y sincroniza la bandera con el buzón del proveedor. |
mark_email_unread | emails:write | Marca un correo como no leído (solo local). |
add_email_tag | tags:write | Adjunta una etiqueta existente del espacio de trabajo a un correo (por tag_id o nombre). Las etiquetas no se crean aquí — usa create_tag. |
remove_email_tag | tags:write | Elimina una etiqueta de un correo. |
update_emails | emails:write | Acción en masa sobre correos. archive/unarchive/trash/snooze/unsnooze actúan sobre hilos completos (espejando la UI de la aplicación). |
move_emails_to_folder | emails:write | Mueve correos (y sus hilos completos) a una carpeta. Pasa folder_name para trabajar entre cuentas. |
tag_emails | tags:write | Añade o elimina una etiqueta en un conjunto de correos. La etiqueta debe existir — usa create_tag para crear nuevas. |
forward_email | emails:send | Reenvía un correo a otra dirección. |
get_skim_deck | emails:read | Devuelve el mazo de skim como anillos compactos y tarjetas de clúster. Aplica decisiones con skim_decide. |
skim_decide | emails:write | Aplica una decisión de triage Skim a los correos de un clúster. Espeja el ciclo de aprendizaje de la UI de la bandeja de entrada (archivar, conservar, promover). |
Cuentas de correo
| Tool | Scope | Finalidad |
|---|
list_email_accounts | email_accounts:read | Lista las cuentas de correo conectadas visibles al llamador. Usa el id como email_account_id para filtrar. |
connect_email_account | email_accounts:write | Conecta una nueva cuenta de correo. mode=web devuelve una URL para abrir en un navegador (flujo OAuth normal — recomendado para usuarios cloud). mode=token acepta un token de actualización pre-creado (ruta OAuth local para autoalojado). |
Documentos
| Tool | Scope | Finalidad |
|---|
list_documents | documents:read | Lista los documentos del espacio de trabajo, del más reciente al más antiguo. Filtros opcionales por id de tipo de documento y estado de revisión. |
get_document | documents:read | Obtiene un documento por id con sus campos extraídos e información del archivo (descarga via download_path del archivo). |
upload_document | documents:write | Sube un nuevo documento desde contenido base64. La clasificación por IA se ejecuta de forma asíncrona. |
update_document | documents:write | Edita los campos extraídos de un documento. No cambia su estado de revisión (usa approve/reject/reclassify para eso). |
approve_document | documents:write | Aprueba (firma) un documento. |
reject_document | documents:write | Rechaza un documento. |
reclassify_document | documents:write | Cambia el tipo de un documento (también lo aprueba). |
| Tool | Scope | Finalidad |
|---|
list_contacts | contacts:read | Lista los contactos del espacio de trabajo. Consulta de texto opcional sobre nombre/correo y filtro de solo favoritos. |
get_contact | contacts:read | Obtiene un único contacto por id. |
update_contact | contacts:write | Actualiza el nombre y/o tipo de relación de un contacto. |
set_contact_state | contacts:write | Marcar/desmarcar como favorito, permitir, bloquear o desbloquear un contacto. |
Etiquetas
| Tool | Scope | Finalidad |
|---|
list_tags | tags:read | Lista las etiquetas del espacio de trabajo (las etiquetas se aplican a correos). |
create_tag | tags:write | Crea una nueva etiqueta en el espacio de trabajo. Las etiquetas se aplican a correos y pueden usarse para filtrar. |
Tipos de documento
| Tool | Scope | Finalidad |
|---|
list_document_types | document_types:read | Lista los tipos de documento del espacio de trabajo (usados para clasificar documentos). |
create_document_type | document_types:write | Crea un nuevo tipo de documento para clasificar adjuntos. |
Carpetas
| Tool | Scope | Finalidad |
|---|
list_folders | folders:read | Lista las carpetas personalizadas del espacio de trabajo. |
get_folder | folders:read | Obtiene una carpeta y los documentos archivados en ella. |
create_folder | folders:write | Crea una carpeta personalizada. Cuando provision: true, la carpeta se crea en cada cuenta de correo conectada como una etiqueta/carpeta del lado del proveedor. |
file_document | folders:write | Archiva un documento en una carpeta. |
unfile_document | folders:write | Elimina un documento de una carpeta (por id de miembro). |
Tareas (funcionalidad condicional)
Los tools de tareas requieren que la funcionalidad Tareas esté habilitada en el servidor (ENABLE_TASKS). Aparecen en tools/list solo cuando la funcionalidad está activa.
| Tool | Scope | Finalidad |
|---|
list_tasks | tasks:read | Lista las tareas del espacio de trabajo. Filtro de estado opcional; include_archived para ver tareas archivadas. |
get_task | tasks:read | Obtiene una tarea por id con detalle completo. |
create_task | tasks:write | Crea una tarea en el espacio de trabajo. |
update_task | tasks:write | Actualiza los campos de una tarea. Los cambios de estado usan la transición adecuada (publica eventos). |
complete_task | tasks:write | Marca una tarea como hecha. |
create_task_from_email | tasks:write | Extrae y crea una tarea a partir de un correo via el registro de acciones. |
Calendario
| Tool | Scope | Finalidad |
|---|
list_calendars | calendar:read | Lista los calendarios visibles al llamador. Usa el id como calendar_id en create_calendar_event. |
list_calendar_events | calendar:read | Lista los eventos de calendario accesibles al llamador, del más próximo al más lejano. Filtros opcionales start_after / start_before. |
get_calendar_event | calendar:read | Obtiene un evento de calendario por id. |
create_calendar_event | calendar:write | Crea un evento de calendario en uno de los calendarios editables del llamador. Los tiempos son ISO-8601. |
update_calendar_event | calendar:write | Actualiza un evento de calendario (debes tener acceso de escritura a su calendario). recurrence_scope: this o all. |
delete_calendar_event | calendar:write | Elimina un evento de calendario (eliminación asíncrona por el proveedor). recurrence_scope: this o all. |
rsvp_calendar_event | calendar:write | Establece tu RSVP en un evento (needs_action, accepted, declined, tentative). |
create_event_from_email | calendar:write | Extrae y crea un evento de calendario a partir de un correo. La IA infiere los detalles del evento; proporciona sustituciones según sea necesario. |
Recordatorios
| Tool | Scope | Finalidad |
|---|
list_reminders | reminders:read | Lista los recordatorios extraídos por IA accesibles al llamador. Filtro de estado opcional (pending, confirmed, dismissed, snoozed). |
get_reminder | reminders:read | Obtiene un recordatorio por id. |
confirm_reminder | reminders:write | Confirma un recordatorio en un evento de calendario. Opcionalmente pasa due_at para ajustar la hora primero. |
dismiss_reminder | reminders:write | Descarta un recordatorio. |
snooze_reminder | reminders:write | Pospone un recordatorio hasta el tiempo indicado, o una semana cuando se omite. |
Correos programados
| Tool | Scope | Finalidad |
|---|
list_scheduled_emails | scheduled_emails:read | Lista correos programados (y recurrentes) en el espacio de trabajo, del más próximo al más lejano. |
get_scheduled_email | scheduled_emails:read | Obtiene un correo programado por id. |
create_scheduled_email | scheduled_emails:write | Programa un correo para enviar más tarde (opcionalmente recurrente via RRULE). Envía desde una cuenta desde la que el usuario puede enviar. |
update_scheduled_email | scheduled_emails:write | Actualiza un correo programado pendiente (destinatario, asunto, cuerpo, hora, rrule). |
cancel_scheduled_email | scheduled_emails:write | Cancela un correo programado (suave: establece el estado a cancelled). |
Scout
| Tool | Scope | Finalidad |
|---|
list_scout_threads | scout:read | Lista los hilos de chat Scout del llamador, del más reciente al más antiguo. |
create_scout_thread | scout:write | Inicia un nuevo hilo de chat Scout. |
list_scout_messages | scout:read | Lista mensajes en un hilo Scout. Pasa after_message_id para esperar la respuesta asíncrona de la IA. |
send_scout_message | scout:write | Publica un mensaje de usuario en un hilo Scout. La respuesta de IA se genera de forma asíncrona; usa list_scout_messages con after_message_id hasta que aparezca. |
Flujos de trabajo (funcionalidad condicional)
Los tools de flujos de trabajo requieren que la funcionalidad Flujos de trabajo esté habilitada en el servidor (ENABLE_WORKFLOWS). Aparecen en tools/list solo cuando la funcionalidad está activa.
| Tool | Scope | Finalidad |
|---|
list_workflows | workflows:read | Lista los flujos de trabajo de automatización del espacio de trabajo. |
trigger_workflow | workflows:trigger | Activa un flujo de trabajo webhook habilitado con un payload JSON opcional. |
list_workflow_executions | workflows:read | Lista el historial de ejecuciones de un flujo de trabajo (del más reciente al más antiguo). |
Plantillas (funcionalidad condicional)
| Tool | Scope | Finalidad |
|---|
list_email_templates | templates:read | Lista las plantillas de correo reutilizables del espacio de trabajo. |
Familias con funcionalidad condicional
Tres familias de tools están ocultas cuando la funcionalidad del servidor correspondiente está deshabilitada:
| Familia | Variable de entorno del servidor | Predeterminado |
|---|
| Tareas | ENABLE_TASKS | deshabilitado |
| Flujos de trabajo | ENABLE_WORKFLOWS | deshabilitado |
| Plantillas | (flag interno) | varía |
Estos tools simplemente no aparecen en tools/list cuando la funcionalidad está deshabilitada — no devuelven un error.
connect_email_account — modo web vs. token
El tool connect_email_account admite dos modos:
mode: "web" — devuelve una ruta relativa para abrir en un navegador. El propio flujo OAuth del servidor gestiona la redirección; esta es la opción correcta para usuarios de Campbooks Cloud y cualquier servidor cuyos callbacks OAuth sean públicamente accesibles.
mode: "token" — acepta un token de actualización pre-creado directamente. Úsalo para instancias autoalojadas donde los callbacks OAuth del servidor no son accesibles desde internet. El token debe haber sido creado con las credenciales OAuth del propio servidor (GOOGLE_CLIENT_ID/ZOHO_CLIENT_ID), o el servidor fallará al actualizarlo. Consulta Claude Code → OAuth local para el script auxiliar.
Garantías de seguridad
Permisos de buzón por usuario — una clave MCP actúa como el usuario que la creó. Buzones que ese usuario no puede leer en la aplicación, la clave tampoco puede. Buzones desde los que ese usuario no puede enviar, la clave tampoco puede. Los OAuth scopes son un techo adicional sobre esos permisos, no un reemplazo.
404-no-403 — los recursos que existen pero pertenecen a un espacio de trabajo diferente devuelven 404, no 403. La API y el servidor MCP nunca revelan si un recurso existe fuera de tus datos.
Confirmar antes de enviar — las skills /campbooks:triage y /campbooks:setup están diseñadas para mostrar el texto completo del borrador y esperar un "sí" explícito antes de llamar a send_email, reply_email o forward_email. Si estás construyendo tu propio prompt de agente sobre los tools MCP, sigue el mismo patrón: nunca llames a un tool de envío sin aprobación del usuario en el mismo turno.