1. Inicio
  2. Servidor MCP
MCP · Model Context Protocol

Outreach por DM en TikTok desde tu LLM

El servidor MCP de Hooka da a Claude, ChatGPT, Cursor o tu propio agente 26 herramientas sobre la API de Hooka. Con ellas puede conectar cuentas de TikTok por QR, crear y lanzar campañas de DM, llevar el inbox y gestionar tu lista No contactar. Usa el servidor alojado en mcp.hooka.to (inicia sesión con OAuth o manda una API key), o ejecútalo en local por stdio con npx hooka-mcp.

Última actualización: 30 de septiembre de 2026 · hooka-mcp 0.3.0 · Por el equipo de Hooka

¿Qué es el servidor MCP de Hooka?

El servidor MCP de Hooka es un servidor Model Context Protocol. Expone la API REST v1 de Hooka como herramientas que tu LLM puede invocar. Cada herramienta corresponde a un único endpoint de https://api.hooka.to/v1 y reenvía tu propia credencial (una API key o un token OAuth). El servidor no guarda credenciales, y se aplican los mismos límites del servidor que si llamaras a la API directamente.

Además de las llamadas a la API, el servidor hace algunas cosas por el modelo:

  • Devuelve el QR de conexión como imagen, para que el asistente te lo enseñe.
  • Manda una clave de idempotencia en las herramientas de escritura que la admiten, para que un reintento no cree una segunda campaña ni envíe un segundo DM.
  • Convierte los errores de la API en una línea legible con el código de error, el campo culpable y el id de la petición.

Los títulos y descripciones de las herramientas, las instrucciones del servidor, los prompts, los resources y las notas y errores que genera el propio servidor (falta la clave, timeout, error de red) están en español. Elegir un prompt añade un mensaje en español a la conversación. Los errores que devuelve la API de Hooka llegan tal cual, en inglés, igual que los de validación del esquema (-32602).

26
herramientas
12
de solo lectura
3
prompts guiados
0.3.0
versión documentada

¿Cómo conecto Hooka a Claude, ChatGPT o Cursor?

Hay tres formas de conectarlo. Todas dan acceso a las mismas 26 herramientas:

OpciónDónde se ejecutaCredencialClientes habituales
Alojado + OAuthhttps://mcp.hooka.to/mcp (Streamable HTTP)Inicias sesión en Hooka y apruebas el accesoClaude.ai, Claude Desktop (conectores), ChatGPT
Alojado + API keyhttps://mcp.hooka.to/mcp (Streamable HTTP)Cabecera Authorization: Bearer hk_live_…Claude Code, Cursor, agentes propios
LocalTu máquina, por stdio (npx hooka-mcp, Node.js 20+)Variable de entorno HOOKA_API_KEYFichero de config de Claude Desktop, Cursor, cualquier cliente stdio

Alojado, con OAuth (Claude.ai, Claude Desktop, ChatGPT)

Añade Hooka como conector personalizado y pega esta URL. No hay nada que instalar ni clave que copiar:

https://mcp.hooka.to/mcp

El cliente descubre el servidor de autorización de Hooka, se registra y te lleva a Hooka para iniciar sesión y aprobar el acceso (OAuth 2.1, con PKCE S256 obligatorio). Después aparecen las herramientas. Conviene saber algunos detalles:

  • La aprobación da acceso completo a tu workspace, igual que una API key live. La única excepción es la gestión de API keys, que los tokens OAuth no pueden hacer.
  • Los tokens de acceso duran 30 minutos. El cliente los renueva con un refresh token, que dura 60 días y rota en cada uso.
  • La pantalla de inicio de sesión y consentimiento está solo en español.

Alojado, con API key (Claude Code, Cursor, agentes propios)

Los clientes que pueden mandar cabeceras HTTP pueden saltarse OAuth y mandar tu clave. En Claude Code:

claude mcp add --transport http hooka https://mcp.hooka.to/mcp --header "Authorization: Bearer hk_live_..."

En Cursor (mcp.json) y otros clientes que usan el formato url + headers:

{
  "mcpServers": {
    "hooka": {
      "url": "https://mcp.hooka.to/mcp",
      "headers": { "Authorization": "Bearer hk_live_..." }
    }
  }
}

El servidor alojado no comprueba la clave al conectar. Con una clave inválida o revocada, las herramientas aparecen igual, y luego cada llamada devuelve 401 authentication_error/invalid_api_key. Para comprobar la configuración, pide al asistente que llame a get_workspace.

En local, por stdio (npx)

El paquete npm hooka-mcp ejecuta el mismo servidor en tu máquina, por stdio. Añade esto a la config MCP de tu cliente:

{
  "mcpServers": {
    "hooka": {
      "command": "npx",
      "args": ["-y", "hooka-mcp"],
      "env": { "HOOKA_API_KEY": "hk_live_..." }
    }
  }
}

En Claude Desktop va en claude_desktop_config.json. Ese fichero solo carga servidores locales, así que para la URL alojada usa un conector. En Cursor, usa el mismo command, args y env. Necesita Node.js 20 o superior. El servidor local lee estas variables de entorno:

  • HOOKA_API_KEY (obligatoria): tu clave. Sin ella el servidor arranca, pero cada herramienta devuelve un error pidiéndola.
  • HOOKA_API_BASE (opcional): la URL base de la API. Por defecto, https://api.hooka.to.
  • HOOKA_API_TIMEOUT_MS (opcional): el timeout de cada llamada a la API. Por defecto, 30000.

Esta página documenta hooka-mcp 0.3.0, la versión del servidor alojado. Las versiones 0.1.x anteriores tienen 23 herramientas y no traen el QR como imagen, la herramienta de verificación ni el comportamiento de reintentos que se describe aquí. Antes de ejecutarlo en local, comprueba qué versión va a bajar npx con npm view hooka-mcp version. Si sale una 0.1.x, la 0.2.0 aún no está en npm: usa el servidor alojado hasta que lo esté. Al conectar, el servidor también comunica su versión a tu cliente (serverInfo).

¿Qué credencial debe usar el agente?

CredencialCómo se obtieneQué puede hacer el agente
hk_live_…La página Developers de tu panel de Hooka (siempre crea claves live), o POST /v1/api_keysLeer y escribir: acciones reales sobre tus cuentas reales de TikTok
hk_test_…POST /v1/api_keys con {"mode":"test"}, autenticado con una clave liveSolo lectura: toda herramienta que escribe devuelve 403 permission_error/test_key_read_only
Token OAuthSe emite al aprobar el conector (solo servidor alojado)Leer y escribir, como una clave live. No puede gestionar API keys.

No hay sandbox. Una clave de prueba lee tu workspace real; no simula envíos. Va bien cuando el agente solo debe mirar: informes, resúmenes del inbox, stats de campañas. Para crear una, llama a la API con una clave live:

curl https://api.hooka.to/v1/api_keys \
  -H "Authorization: Bearer hk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"mode":"test","label":"agente solo lectura"}'
{
  "id": "key_6a1e…",
  "object": "api_key",
  "mode": "test",
  "prefix": "hk_test_1a2b3c",
  "secret": "hk_test_1a2b3c…"
}

El secret se muestra una sola vez. Con una clave de prueba funcionan las lecturas, incluida get_workspace. Toda escritura falla igual, sea cual sea la herramienta:

403 permission_error/test_key_read_only: Test keys (hk_test_) are read-only: Hooka has no sandbox, so any write would act on your real TikTok accounts. Use an hk_live_ key to create, start or send. [request_id req_…]

Todas las claves y tokens OAuth de un workspace comparten su límite de 300 peticiones a la API por minuto, junto con el tráfico directo a la API.

¿Qué puede hacer el agente? Las 26 herramientas

Cada herramienta llama a un endpoint de la API v1 de Hooka. Las de lectura llevan la anotación MCP readOnlyHint. Las marcadas como destructivas llevan destructiveHint porque envían DMs reales, cortan conexiones o vuelven a permitir el contacto. Los clientes que respetan las anotaciones pueden preguntarte antes de ejecutarlas.

HerramientaQué haceLlamada a la APITipo
Senders (cuentas de TikTok) · 7
list_sendersTodas las cuentas de TikTok (senders) del workspace, en cualquier estado, con status_reason, health, daily_limit y sent_today. Filtro status opcional.GET /v1/senderslectura
get_senderUn sender. Es la herramienta que se consulta durante una conexión: mientras connection.status es requires_scan, el QR llega como imagen.GET /v1/senders/{id}lectura
create_senderInicia la conexión de una cuenta de TikTok por QR (sin contraseña). country es el país de la cuenta: recibe su propia IP residencial dedicada de allí, y el país no se puede cambiar después. Devuelve el sender en awaiting_scan, todavía sin QR. Ocupa una plaza y cancela cualquier otra conexión en curso del workspace.POST /v1/sendersdestructiva
refresh_sender_connectionUn intento de conexión nuevo (QR nuevo) para un sender que no está conectado: caducado, desconectado, en cooldown o baneado. Conserva la IP propia del sender.POST /v1/senders/{id}/connection/refreshdestructiva
verify_sender_connectionCompleta el paso "Verifica que eres tú" que TikTok pide tras escanear: elige correo o teléfono, manda el código o pide otro.POST /v1/senders/{id}/connection/verifyescritura
update_senderCambia la etiqueta de un sender, el único campo que la API puede editar.PATCH /v1/senders/{id}escritura
delete_senderDesconecta una cuenta. El sender sigue en la lista como disconnected y libera su plaza. También cancela una conexión por QR en curso de ese sender. Las campañas running que se quedan sin ningún sender conectado se pausan, y los seguimientos pendientes que solo podía enviar esta cuenta se omiten (sender_unavailable).DELETE /v1/senders/{id}destructiva
Campañas · 8
list_campaignsCampañas, de la más nueva a la más antigua. Las archivadas no aparecen.GET /v1/campaignslectura
get_campaignUna campaña con stats en vivo: pending, processing, sent, failed, skipped, replied, reply_rate.GET /v1/campaigns/{id}lectura
create_campaignCrea un borrador. Admite un mensaje o hasta 20 variantes, hasta 10 seguimientos, hasta 1.000 destinatarios, hasta 10 senders y ajustes de ritmo. No envía nada.POST /v1/campaignsescritura
add_targetsAñade hasta 1.000 destinatarios por llamada. En una campaña running empiezan a recibir DMs en segundos. Una campaña completed se reabre (resumed: true) si alguno de sus senders está conectado. Si no hay ninguno, la respuesta trae resume_blocked_reason: "no_connected_sender": reconecta un sender y llama a start_campaign o resume_campaign.POST /v1/campaigns/{id}/targetsdestructiva
list_targetsDestinatarios en orden de alta, con su estado y un código error estable si falló o se omitió. Filtro status opcional.GET /v1/campaigns/{id}/targetslectura
start_campaignArranca el envío de DMs reales. Vale para un borrador (draft), una campaña paused o una completed que aún tiene destinatarios pendientes.POST /v1/campaigns/{id}/startdestructiva
pause_campaignPausa una campaña running. Un DM que ya se está enviando puede llegar a salir.POST /v1/campaigns/{id}/pauseescritura
resume_campaignReanuda el envío de una campaña paused, o de una completed que aún tiene destinatarios pendientes.POST /v1/campaigns/{id}/resumedestructiva
Inbox · 4
list_conversationsConversaciones por actividad más reciente. Filtros status y sender_id opcionales.GET /v1/conversationslectura
get_conversationUna conversación: qué sender, la otra persona, estado, no leídos y último mensaje.GET /v1/conversations/{id}lectura
get_messagesLos mensajes de una conversación, del más antiguo al más nuevo (in = la otra persona, out = tú).GET /v1/conversations/{id}/messageslectura
send_replyEncola una respuesta de 1 a 2.000 caracteres. Sale como DM real desde el sender de la conversación en segundos.POST /v1/conversations/{id}/messagesdestructiva
Lista No contactar · 3
list_suppressionsLos usernames a los que nunca se debe escribir, con su reason (manual, opt_out…).GET /v1/suppressionslectura
add_suppressionsAñade de 1 a 1.000 usernames. Sus destinatarios pendientes en todas las campañas se omiten en el acto.POST /v1/suppressionsescritura
remove_suppressionQuita un username. Eso puede volver a permitir DMs a alguien que pidió que no le escribieran.DELETE /v1/suppressions/{username}destructiva
Eventos, webhooks y workspace · 4
list_eventsEventos del workspace, los mismos que llegan por webhook, guardados 30 días. Recórrelos del más nuevo al más antiguo, o consulta los nuevos con after.GET /v1/eventslectura
list_webhook_endpointsTus endpoints de webhook, sin sus secrets.GET /v1/webhook_endpointslectura
create_webhook_endpointCrea un endpoint (URL https:// pública). Devuelve el secret de firma whsec_… una sola vez.POST /v1/webhook_endpointsescritura
get_workspaceWhoami: id del workspace, país por defecto de las cuentas nuevas (exit_ip.region) y plazas.GET /v1/workspacelectura

Las listas paginadas admiten limit (1-100, por defecto 50) y starting_after (el next_cursor de la página anterior). Pásalo mientras has_more sea true. list_webhook_endpoints no pagina.

Ejemplos

Conectar una cuenta de TikTok

Dices: "Conecta mi cuenta de TikTok y ponle la etiqueta Tienda ES." El agente sigue estos pasos:

  1. get_workspace: comprueba que queda una plaza libre (seats.used < seats.limit; un limit null significa sin tope) y lee el país por defecto (exit_ip.region). Si la cuenta es de otro país, el agente te lo pregunta.
  2. create_sender {"label":"Tienda ES","country":"ES"}: el sender vuelve en awaiting_scan con connection.status "pending" y todavía sin QR. La cuenta recibe su propia IP residencial dedicada de ese país; mientras se prepara, exit_ip.status es "provisioning".
  3. get_sender cada 3-5 segundos. connection.status pasa por pending, requires_scan, scanned, a veces verification_required, y termina con el sender connected.
  4. En requires_scan, el resultado de la herramienta trae el QR como imagen y lo escaneas con la app de TikTok. El QR se renueva solo; el agente te enseña siempre el último.
  5. En verification_required, te pregunta dónde quieres recibir el código y cuál es. Luego llama a verify_sender_connection, por ejemplo {"id":"snd_…","action":"submit_code","code":"482913"}.

Así se ve un resultado de get_sender con el QR listo (resumido):

{
  "content": [
    { "type": "text", "text": "{ \"id\": \"snd_…\", \"object\": \"sender\", \"status\": \"awaiting_scan\", \"connection\": { \"status\": \"requires_scan\", \"qr_code\": \"[QR adjunto como imagen en esta respuesta: …]\", … } }" },
    { "type": "image", "data": "iVBORw0KGgo…", "mimeType": "image/png" }
  ]
}

El intento ha fallado si connection.status pasa a expired o failed (connection.error dice por qué), o si el sender pasa a disconnected (status_reason dice por qué). El agente deja de consultar y puede ofrecer refresh_sender_connection para un QR nuevo. Conecta las cuentas de una en una, porque cada intento nuevo cancela el que esté en curso.

Crear una campaña y arrancarla solo cuando confirmes

Dices: "Prepara una campaña para estos dos creadores con un seguimiento a los 3 días, 90 segundos entre DMs y como mucho 40 al día." El agente llama a:

{
  "name": "create_campaign",
  "arguments": {
    "name": "Creadores ES - octubre",
    "message": {
      "variants": [
        "Hola {{first_name}}, me encantó tu último vídeo. ¿Te interesa una colaboración pagada?",
        "Hola {{first_name}}, buscamos creadores como tú. ¿Te lo cuento?"
      ]
    },
    "follow_ups": [
      { "wait_days": 3, "variants": ["{{first_name}}, ¿pudiste ver mi mensaje?"] }
    ],
    "targets": [
      { "username": "@maria.ugc", "variables": { "first_name": "María" } },
      { "username": "@leo_creates", "variables": { "first_name": "Leo" } }
    ],
    "settings": { "rate_limit_seconds": 90, "daily_limit": 40 }
  }
}

El resultado es la campaña con "status": "draft", más targets_accepted, target_ids y targets_skipped. En este punto no se ha enviado nada. Algunas notas sobre los argumentos:

  • Sin settings.sender_ids, la campaña usa hasta 10 de los senders conectados más antiguos del workspace.
  • daily_limit limita la campaña entera por día. Cada cuenta mantiene además su propio tope diario.
  • Los seguimientos salen desde la misma cuenta que envió el primer DM y se paran cuando la persona responde.

Después, el agente te enseña un resumen y te pregunta antes de llamar a start_campaign {"id":"cmp_…"}. Se lo piden tanto las instrucciones del servidor como el prompt launch_campaign.

Triar el inbox con una clave de solo lectura

Con una clave hk_test_, el agente puede usar list_conversations {"status":"open"} y get_messages, clasificar las respuestas en interesado, pregunta, no interesado o spam, y redactarte respuestas. No puede enviarlas: send_reply devuelve 403 test_key_read_only. Tú revisas los borradores y los envías, o cambias a una clave live.

Ver qué pasó durante la noche

"¿Qué ha pasado en mis campañas desde ayer?" El agente lee list_events, por ejemplo con type igual a target.replied o sender.status_changed, y get_campaign para las stats. El resource hooka://event-types explica qué significa cada tipo de evento.

Prompts, resources e instrucciones del servidor

Prompts (flujos guiados que el usuario puede elegir en los clientes que los admiten):

  • launch_campaign (argumento opcional goal). Comprueba que hay una cuenta conectada, propone un mensaje con 2-3 variantes y seguimientos, crea el borrador y te pide confirmación explícita antes de start_campaign.
  • triage_inbox. Recorre las conversaciones abiertas, las clasifica y redacta respuestas breves. Espera tu OK antes de cualquier send_reply.
  • connect_account (argumento opcional label). Sigue el flujo de QR de arriba, incluido el paso de verificación de TikTok.

Resources (texto de solo lectura; no llaman a la API, así que funcionan con cualquier clave):

  • hooka://event-types recoge los 12 tipos de evento de webhook más ping, con lo que significa cada uno.
  • hooka://api-reference cubre la URL base, los prefijos de id, la paginación, la idempotencia, el formato de error y el límite de peticiones.

Las instrucciones del servidor se envían en initialize. Cubren lo siguiente: que las claves de prueba son de solo lectura, qué herramientas envían DMs reales y necesitan tu confirmación, el flujo de conexión, la paginación, la idempotencia y el formato de error.

¿Qué no puede hacer el agente?

El servidor MCP solo puede hacer lo que permite la API. Algunas cosas son solo del panel o no están expuestas:

  • Pago, plan y país por defecto. La suscripción y el país por defecto se cambian en el panel; get_workspace solo los lee. El país de cada cuenta se fija con create_sender y no se puede cambiar después (soporte de Hooka puede moverla).
  • Tope diario por cuenta y calentamiento. Solo se cambian en el panel. El tope es de 30 DMs al día por cuenta por defecto (ajustable hasta 100). El daily_limit de una campaña no puede subirlo.
  • Editar campañas. Ningún endpoint edita, archiva ni borra una campaña. Por la API, el mensaje, los seguimientos y los senders de una campaña no cambian después de crearla (el editor de campañas del panel sí puede cambiarlos).
  • Estado de las conversaciones. open, interested y los demás estados son de solo lectura por la API.
  • Mantenimiento de webhooks. Probar, editar o borrar un endpoint, y leer un evento suelto por id, existen en la API pero no como herramientas.
  • API keys. No hay herramienta para ellas. Los tokens OAuth reciben 403 oauth_token_not_allowed en las rutas de claves.
  • Automatizaciones de comentario a DM. Se gestionan en el panel y no están expuestas por la API.
  • Ajustes que no existen. create_campaign.settings es estricto, así que sender_pool, stop_on_reply o cualquier otra clave desconocida da un error de validación. Los seguimientos siempre se paran cuando la persona responde.
  • Otras plataformas. Solo TikTok.
  • Notificaciones push. El servidor alojado no guarda estado y no envía notificaciones. Consulta list_events o crea un endpoint de webhook para tu backend.

Qué significa "enviado". send_reply responde {"id":"rpl_…","object":"message","status":"queued"}, y el DM sale en segundos. Un destinatario cuenta como sent cuando TikTok aceptó el mensaje y no mostró ningún aviso de "no entregado" en los segundos siguientes. No prueba que la persona lo haya leído. Si el envío no se puede confirmar, el destinatario queda failed con send_unconfirmed y no se reintenta nunca, para no duplicar el DM.

¿Es seguro dejar que una IA mande DMs?

Cuatro acciones envían DMs reales e irreversibles: start_campaign, resume_campaign, send_reply, y add_targets sobre una campaña running o completed. Las instrucciones del servidor piden al modelo tu confirmación explícita antes de cada una.

Ocho herramientas llevan la anotación destructiveHint:

  • las cuatro anteriores;
  • create_sender y refresh_sender_connection, que cancelan otras conexiones en curso;
  • delete_sender;
  • remove_suppression, que puede volver a permitir el contacto con quien pidió la baja.

Que el cliente pregunte antes de una herramienta destructiva depende del cliente y de tu configuración.

Hooka aplica los mismos límites a cualquiera que lo use, sea el panel, la API o el MCP:

  • Un tope diario por cuenta.
  • Espaciado entre DMs de la misma cuenta: rate_limit_seconds, 30-3600, 60 por defecto.
  • Un tope diario opcional por campaña.
  • Seguimientos que se paran cuando la persona responde.
  • Deduplicación entre campañas (activada por defecto).
  • La lista No contactar.

Las cuentas se conectan por QR; Hooka nunca pide tu contraseña de TikTok.

Nota honesta: automatizar DMs en TikTok opera fuera de la API oficial de TikTok y tiene un riesgo real; ninguna herramienta puede prometer cero bans. El servidor MCP no cambia eso. Le da a tu LLM una forma estructurada de manejar Hooka con tu confirmación. Usa cuentas dedicadas al outreach y empieza con volúmenes bajos.

Reintentos, idempotencia y errores

Estas 10 herramientas de escritura aceptan un idempotency_key opcional y mandan siempre una cabecera Idempotency-Key:

  • create_sender, refresh_sender_connection, verify_sender_connection
  • create_campaign, add_targets, start_campaign, pause_campaign, resume_campaign
  • send_reply, create_webhook_endpoint

Cómo funciona la clave:

  • Clave derivada. Sin idempotency_key, la clave sale del nombre de la herramienta, los argumentos y la ventana fija de 10 minutos del reloj en curso (12:00-12:10, 12:10-12:20…). Una llamada idéntica en la misma ventana devuelve el resultado guardado con una nota en vez de ejecutarse otra vez. En la ventana siguiente se ejecuta de nuevo, aunque sea segundos después. Hay dos excepciones, en las que el MCP pasa a la siguiente clave de la serie (hasta 5 por ventana) y la llamada se ejecuta otra vez: que el resultado guardado fuera un error 4xx o, en create_sender y refresh_sender_connection, que aquel intento de conexión ya haya terminado (el sender ya no está en awaiting_scan, o connection.status es expired o failed). Así, repetir la misma llamada a create_sender en la misma ventana, para otra cuenta después de que la primera se conectara, sí empieza una conexión nueva. Con un idempotency_key explícito no hay excepciones.
  • Timeouts y errores de red. El texto del error trae la clave exacta que se mandó, así que la llamada se puede reintentar con idempotency_key igual a esa clave: si la original terminó, recibes su resultado guardado en vez de una segunda ejecución; si sigue en curso, recibes 409 idempotency_key_in_use (espera y reintenta con la misma clave). Una petición atascada más de 5 minutos se da por muerta y se ejecuta de nuevo. Hooka guarda las claves 24 horas.
  • 409 idempotency_key_in_use. La petición original sigue en curso. Espera unos segundos y reintenta con la misma clave.
  • Repetir a propósito. Para pausar otra vez tras reanudar, o para pedir otro código de verificación, pasa un idempotency_key nuevo.
  • Herramientas sin clave. add_suppressions (idempotente por naturaleza), update_sender, delete_sender y remove_suppression no mandan ninguna.

Los errores de las herramientas llegan con isError: true y una sola línea de texto:

<status> <type>/<code>: <message> (param: <field>) [request_id req_…]
409 conflict_error/invalid_campaign_state: Cannot start a campaign that is running. [request_id req_…]
400 invalid_request_error/no_sender_available: Cannot start this campaign: none of its senders is connected. Reconnect one (POST /v1/senders/{id}/connection/refresh) and retry. [request_id req_…]
429 rate_limit_error/rate_limited: Too many requests. Retry in 7 s. (Retry-After: 7 s) [request_id req_…]

El servidor valida los argumentos contra el esquema de cada herramienta antes de llamar a la API. Un argumento incorrecto devuelve MCP error -32602: Input validation error: …. Los argumentos desconocidos de primer nivel se descartan sin avisar. create_campaign.settings es la excepción: ahí una clave desconocida es un error. Cada llamada a la API tiene un timeout de 30 segundos, y en ese caso el error dice que la acción pudo aplicarse o no.

¿Puedo llamar al servidor alojado desde mi propio código?

Sí. https://mcp.hooka.to/mcp habla MCP Streamable HTTP en modo sin estado (stateless). Sigue estas reglas:

  • Manda JSON-RPC con POST /mcp. GET y DELETE dan 405, y no hay Mcp-Session-Id.
  • Manda Accept: application/json, text/event-stream. Sin los dos tipos, recibes 406.
  • Las respuestas llegan como server-sent events.
  • Manda siempre un objeto arguments, aunque esté vacío: un tools/call sin él no pasa la validación.
curl -N https://mcp.hooka.to/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Authorization: Bearer hk_live_..." \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_workspace","arguments":{}}}'
event: message
data: {"result":{"content":[{"type":"text","text":"{\n  \"id\": \"ws_…\",\n  \"object\": \"workspace\",\n  \"name\": \"Default\",\n  \"created\": 1790726400,\n  \"exit_ip\": {\n    \"status\": \"ready\",\n    \"region\": \"ES\",\n    \"suggested_region\": null,\n    \"per_sender\": true\n  },\n  \"seats\": {\n    \"limit\": 3,\n    \"used\": 1\n  }\n}"}]},"jsonrpc":"2.0","id":1}

El resultado de una herramienta es un elemento de texto con el JSON de la API (con sangría), más un elemento de imagen cuando va un QR. Cuando la API no devuelve cuerpo, el texto es OK. En una llamada repetida (la misma llamada idempotente otra vez dentro de la ventana de 10 minutos de su clave, o un idempotency_key ya usado), el primer elemento de texto es una línea NOTA: …, el JSON va en el siguiente elemento de texto y no se adjunta la imagen del QR. En create_sender, refresh_sender_connection, verify_sender_connection, start_campaign, pause_campaign y resume_campaign, esa nota trae además el estado actual (Estado ACTUAL: …). Busca el elemento con el JSON en vez de dar por hecho que es content[0]. No hay structuredContent. Un cliente real suele llamar antes a initialize, para recibir las instrucciones del servidor.

Otros endpoints del servidor alojado:

  • GET https://mcp.hooka.to/health devuelve {"ok":true,"service":"hooka-mcp","version":"0.3.0","transport":"streamable-http"}.
  • Los clientes OAuth descubren el servidor de autorización en /.well-known/oauth-protected-resource/mcp. El servidor de autorización es https://api.hooka.to. Admite registro dinámico de clientes y exige PKCE S256, y el recurso es https://mcp.hooka.to/mcp.

Si solo necesitas HTTP, puedes saltarte el MCP y llamar directamente a la API REST. Referencia completa: app.hooka.to/docs.html.

Preguntas frecuentes

¿Qué es el servidor MCP de Hooka?

Un servidor Model Context Protocol que expone la API v1 de Hooka como 26 herramientas, para que Claude, ChatGPT, Cursor o tu propio agente conecten cuentas de TikTok, creen y lancen campañas de DM, lleven el inbox y gestionen la lista No contactar en lenguaje natural. Cada herramienta llama a un endpoint de la API de Hooka con tu credencial, y el servidor no guarda credenciales. Esta página documenta la versión 0.2.0 (licencia MIT); las 0.1.x anteriores de npm tienen 23 herramientas.

¿Cómo conecto Hooka a Claude, ChatGPT o Cursor?

Alojado: añade https://mcp.hooka.to/mcp como conector personalizado en Claude.ai, Claude Desktop o ChatGPT e inicia sesión en Hooka (OAuth 2.1). En clientes que mandan cabeceras, como Claude Code y Cursor, usa la misma URL con Authorization: Bearer hk_live_.... En local: ejecuta npx -y hooka-mcp por stdio con HOOKA_API_KEY y tu clave (Node.js 20+). Las 26 herramientas necesitan hooka-mcp 0.2.0 o posterior: compruébalo con npm view hooka-mcp version.

¿Necesito una API key?

Con el conector OAuth, no: inicias sesión en Hooka y apruebas el acceso. La opción con cabecera y el servidor local sí necesitan una: crea una clave hk_live_ en la página Developers de tu panel. Las claves hk_test_ son de solo lectura: toda herramienta que escribe devuelve 403 permission_error/test_key_read_only.

¿Puedo probarlo sin enviar DMs reales?

No hay sandbox. Una clave hk_test_ deja al agente leer tu workspace real sin cambiar nada. Con una clave live, create_campaign solo crea un borrador y no se envía nada hasta start_campaign. Las herramientas que envían DMs reales son start_campaign, resume_campaign, send_reply, y add_targets sobre una campaña en marcha o terminada.

¿Es seguro dejar que una IA mande DMs en TikTok?

El servidor marca 8 herramientas como destructivas (envían DMs, cortan conexiones o vuelven a permitir el contacto), así que los clientes que respetan las anotaciones MCP pueden preguntarte antes, y sus instrucciones piden al modelo tu confirmación explícita antes de enviar. Hooka aplica los mismos límites a cualquiera que lo use: un tope diario por cuenta, espaciado entre DMs, seguimientos que se paran cuando la persona responde y la lista No contactar. Automatizar TikTok siempre tiene algún riesgo, así que revisa cada acción antes de confirmarla.

¿Puede el agente enseñarme el QR para conectar una cuenta?

Sí. create_sender inicia la conexión y el agente consulta get_sender cada 3-5 segundos. Cuando connection.status es requires_scan, el QR llega como imagen en el resultado de la herramienta y lo escaneas con la app de TikTok. Si después TikTok pide verificar que eres tú, el agente completa ese paso con verify_sender_connection y el código que recibes.

¿Cuánto cuesta?

El servidor MCP es gratis (licencia MIT). Para conectar cuentas de TikTok y enviar DMs hace falta una suscripción activa de Hooka, con precio por cuenta de TikTok conectada. Sin ella, create_sender devuelve 403 permission_error/no_active_subscription.

Sigue leyendo

Deja que tu LLM haga el outreach

Cancela cuando quieras. No pedimos tu contraseña de TikTok. Pago seguro con Stripe.