TimelinesAI MCP Server

TimelinesAI MCP Server

Enables Claude to read and operate a TimelinesAI WhatsApp team inbox, including chats, messages, labels, assignments, and sending, with built-in read-only and confirmation safeguards.

Category
访问服务器

README

TimelinesAI MCP Server

Servidor MCP (Model Context Protocol) que expone la API pública de TimelinesAI —el inbox de WhatsApp para equipos— a Claude. Pensado para desplegarse en Railway en modo solo lectura.

👉 Los pasos de despliegue están en DEPLOY-RAILWAY.md.


Qué hace

Da a Claude 12 herramientas para leer y operar el inbox: chats, mensajes, etiquetas, responsables, números conectados y equipo — más una herramienta genérica, una de descubrimiento, y un resumen agregado del inbox.

Herramienta Endpoint
timelines_whoami verifica el token, el workspace y las rejas
timelines_request cualquier endpoint, cualquier método
timelines_discover sondea rutas y reporta cuáles existen
timelines_list_chats GET /chats con todos los filtros
timelines_get_chat GET /chats/{id}
timelines_list_messages GET /chats/{id}/messages
timelines_send_message POST /messages o /chats/{id}/messages
timelines_update_chat PATCH /chats/{id}
timelines_manage_labels GET/POST/PUT /chats/{id}/labels
timelines_list_whatsapp_accounts GET /whatsapp_accounts
timelines_list_teammates GET /workspace/teammates
timelines_activity_summary pagina /chats y cuenta todo (50 por página)

Variables de entorno

Variable Requerida Default Descripción
TIMELINES_API_TOKEN Token de la API (tla_...)
TIMELINES_MCP_TRANSPORT en Railway stdio http para servidor remoto
MCP_AUTH_TOKEN si http Secreto que protege el endpoint. Mínimo 32 caracteres
TIMELINES_READ_ONLY no ver abajo 1 bloquea toda escritura
TIMELINES_ALLOW_SEND no 0 Reja aparte: enviar mensajes de WhatsApp
TIMELINES_API_BASE no https://app.timelines.ai/integrations/api Para apuntar a otro host
TIMELINES_MAX_CHARS no 20000 Truncado de respuestas
TIMELINES_TIMEOUT no 45 Timeout en segundos
PORT no 8000 Railway lo inyecta solo

Las tres rejas

Este MCP habla con personas reales. Un mensaje enviado por WhatsApp llega al teléfono de alguien en segundos y no se puede deshacer. Por eso hay tres candados independientes.

1. TIMELINES_READ_ONLY — el default depende del transporte

  • stdio (local): escrituras permitidas por default.
  • http (remoto): escrituras bloqueadas por default.

Olvidar la variable en un despliegue público lo deja en solo lectura.

2. TIMELINES_ALLOW_SEND — la reja de envío

Apagada por default en los dos transportes, incluso en local. Aunque habilites las escrituras, enviar mensajes sigue bloqueado hasta que pongas TIMELINES_ALLOW_SEND=1.

La razón es la asimetría: cambiar una etiqueta, reasignar un chat o cerrarlo son acciones internas y reversibles. Mandar un WhatsApp a un cliente no lo es. No tiene sentido que compartan el mismo interruptor.

3. confirm=true — la reja por llamada

Todo envío exige confirm=true además de lo anterior, igual que borrar un archivo, reconfigurar un webhook o revocar el acceso de un compañero. La instrucción de la herramienta es explícita: primero muéstrale al usuario el destinatario exacto y el texto exacto, y solo con su visto bueno se confirma.

Cada rechazo dice cuál de las tres rejas lo detuvo.


Autenticación del endpoint

El protocolo MCP no trae autenticación propia. En modo http, este servidor exige Authorization: Bearer <MCP_AUTH_TOKEN> en cada request, o el secreto embebido en la ruta (/s/<secreto>/mcp) para los connectors de Claude. /healthz es la única ruta pública.

El servidor se niega a arrancar si MCP_AUTH_TOKEN falta o tiene menos de 32 caracteres.


Correr en local

pip install -r requirements.txt

# stdio (para Claude Desktop)
TIMELINES_API_TOKEN=tla_xxx python timelines_mcp.py

# http (como en Railway)
TIMELINES_MCP_TRANSPORT=http \
TIMELINES_API_TOKEN=tla_xxx \
MCP_AUTH_TOKEN=$(python3 -c "import secrets;print(secrets.token_urlsafe(48))") \
PORT=8000 python timelines_mcp.py

Al arrancar imprime en qué modo quedó:

[timelines-mcp] streamable-http on 0.0.0.0:8000  token=set  read_only=True  allow_send=False  sending_enabled=False

Notas sobre la API de TimelinesAI

Verificado contra la referencia pública (https://timelines.ai/docs/public-api-reference/overview):

  • Base: https://app.timelines.ai/integrations/api, auth Authorization: Bearer <tla_...>.

  • Los cuerpos van en JSON, no form-encoded.

  • Las respuestas vienen envueltas: {"status":"ok","data":{...}}. Y hay fallos que llegan con HTTP 200 pero status:"error" — este servidor los trata como error, no como éxito, porque si no un envío fallido se leería como enviado.

  • Los errores traen detalle por campo: {"status":"error","message":..., "error_code":...,"errors":[{"fields":["phone"],"msg":"..."}]}. Se muestran tal cual en el mensaje de error.

  • Los filtros de varios valores van separados por coma en un solo parámetro (label=vip,enterprise), no repetidos ni con corchetes. Pasar una lista de Python produce esa forma.

  • El tamaño de página es fijo en 50 y no se puede cambiar. Verificado contra la API en vivo el 2026-08-25: limit, per_page, page_size, size, count, take y rows se ignoran todos, y cada página llega con 50 registros. El único parámetro que hace algo es page, y has_more_pages en la respuesta dice si hay otra. Por eso las herramientas no exponen un per_page: sería un parámetro que aparenta ajustar y no ajusta nada.

  • Para reducir el tamaño de una respuesta, entonces, no queda bajar la página: hay que filtrar más, o usar fields para quedarte solo con las claves que necesitas. Los mensajes son el caso que más lo pide — un chat con 50 mensajes se pasa del límite de caracteres sin problema. fields=["uid","text", "from_me","timestamp"] deja lo esencial de una conversación en una fracción del tamaño.

  • Ojo con los nombres de campo repetidos: un registro de mensaje trae su propia clave data (un dict de metadatos), además del data de la envoltura. Por eso fields decide qué podar por posición (lo que está dentro de una lista es un registro) y no por el nombre de la clave.

  • Los teléfonos van en formato internacional con +: +5215512345678. El modelo lo valida antes de salir a la red y limpia espacios y guiones.

  • text tiene tope de 2000 caracteres; las etiquetas 64, los nombres de chat 256.

  • Si omites whatsapp_account_phone, TimelinesAI manda desde la cuenta conectada más recientemente — que rara vez es la que el usuario tiene en mente. Con más de un número conectado, conviene ser explícito.

  • Los envíos se espacian ~2 segundos entre uno y otro por política de WhatsApp, y cada mensaje consume créditos (1 texto, 2 con adjunto; los fallidos se reembolsan).

  • Hay tres límites distintos y conviene no confundirlos:

    Límite Valor Aplica a
    Tasa de peticiones 50 por minuto por workspace Todo, lecturas incluidas
    Volumen mensual 200,000 llamadas al mes Todo
    Cuota de mensajería según tu plan (créditos) Solo envíos

    El primero es el que muerde: pasarse devuelve 429 rate_limit_exceeded a media faena, no al principio.

    El servidor se defiende en dos niveles, ambos en la capa de peticiones para que todas las herramientas queden cubiertas, no solo las que paginan:

    1. Ritmo compartido. Las llamadas se espacian 1.2 s entre sí (60÷50). Una llamada suelta no espera nada; el retraso solo aparece en ráfagas, que es justo el caso que topa el límite. El límite es por workspace y todas las herramientas comparten uno, así que el marcapasos también es único.
    2. Reintento con Retry-After. Un 429 en una lectura se reintenta una vez, esperando exactamente lo que pide el servidor. Un envío nunca se reintenta solo: un mensaje que quizá salió no se repite por corazonada.

    timelines_activity_summary además devuelve lo que alcanzó a contar con una nota stopped_early si aun así lo cortan. Para preguntas por persona conviene filtrar (responsible=alguien@...) en lugar de escanear páginas: una petición en vez de veinte. Se pueden pedir límites mayores escribiendo a hello@timelines.ai.

  • No hay endpoint de agregación. Por eso timelines_activity_summary pagina y cuenta del lado del servidor MCP, y avisa con complete=false cuando el conteo no llegó al final.


Seguridad

  • Los secretos van en variables de entorno, nunca en el código. El .gitignore bloquea archivos .env.
  • Un token de TimelinesAI da acceso a todo el workspace: todas las conversaciones de WhatsApp del equipo, con sus teléfonos y su contenido. Es información de clientes reales — trátala como tal.
  • Un solo token compartido significa cero trazabilidad por persona.
  • Para cortar el acceso de golpe: revoca el token en el dashboard de TimelinesAI — el servidor queda inútil al instante.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选