FirmLedger
Busca y accede a inteligencia empresarial y de compañías verificada y respaldada por fuentes a través de FirmLedger.
Servidor MCP alojado
npx add-mcp 'https://firmledger.co.ke/mcp'Se instala en Claude Code, Codex, Cursor y más
Documentación
Un servidor de Model Context Protocol para el libro mayor de FirmLedger. Tiene 46 herramientas: búsquedas de directorio de solo lectura, lecturas de la cuenta del propietario de la clave, cambios de cuenta que siempre requieren la confirmación explícita del usuario y enlaces de pago que nunca cobran nada. Sigue exactamente el modelo de permisos del sitio web. ¿Configurándolo en una aplicación de IA? Comience con la guía de configuración en lenguaje sencillo.
En esta página
Endpoint y transporte Autenticación Niveles de acceso y alcances Protocolo de confirmación Enlaces de pago Formato de resultados Herramientas (46) Herramientas abiertas (12) Herramientas de directorio Pro (4) Lecturas de cuenta (11) Cambios de cuenta (19) Errores Límites Garantías de seguridad Ejemplos en bruto
Dirección principal de conexión de IA: https://mcp.firmledger.co.ke/mcp. Este subdominio solo de DNS evita Cloudflare y llega a la misma aplicación. La antigua https://firmledger.co.ke/mcp sigue activa, pero su capa de seguridad de Cloudflare actualmente desafía a la mayoría de los clientes de IA automatizados. Actualice las configuraciones de los clientes y las entradas del registro a la nueva dirección; conserve su clave y permisos existentes. Por qué hay dos puertas de entrada al mismo servidor.
Endpoint y transporte
| URL | https://mcp.firmledger.co.ke/mcp (o https://mcp.firmledger.co.ke/mcp/<api_key>, ver más abajo) |
|---|---|
| Transporte | HTTP de transmisión, sin estado. POST JSON-RPC 2.0, respondido como application/json. No hay sesiones, por lo que no se emite Mcp-Session-Id. GET devuelve 405 porque el servidor no tiene transmisión iniciada por el servidor (los clientes configurados para el transporte SSE más antiguo fallan aquí). Un navegador (Accept: text/html) es redirigido a la guía de configuración. |
| Capacidades | Solo tools, más instructions del servidor que le indican al modelo cómo funcionan las reglas de confirmación y pago. Las annotations de la herramienta son precisas: las herramientas de directorio y lectura de cuenta llevan readOnlyHint: true. Los cambios de cuenta llevan readOnlyHint: false con destructiveHint / idempotentHint por herramienta, de modo que los clientes que preguntan antes de los efectos secundarios (ChatGPT, VS Code y otros) lo hacen. |
| Construido sobre | El @modelcontextprotocol/sdk oficial, montado dentro de la aplicación web de FirmLedger. Nombre del servidor firmledger. |
| CORS | Access-Control-Allow-Origin: *. La autenticación es por clave, nunca por cookie, por lo que los clientes basados en navegador funcionan y una sesión de navegador nunca puede ser secuestrada. |
| Caché | Cache-Control: no-store, X-Robots-Tag: noindex. Cada respuesta lleva X-Request-Id. |
Autenticación
Las claves son claves API ordinarias de FirmLedger (fl_live_ + 32 caracteres), creadas en /dashboard/api. Cada clave necesita el alcance read:listings. Envíela de una de estas tres maneras:
preferidoAuthorization: Bearer fl_live_tu_clave # X-API-Key: fl_live_tu_clave ← alternativa aceptada # POST https://mcp.firmledger.co.ke/mcp/fl\_live\_your\_key ← URL de conector personal
Por qué existe una URL con clave en la ruta. La API REST rechaza claves en las URL. El endpoint MCP acepta una porque los conectores personalizados de ChatGPT solo pueden usar OAuth o ninguna autenticación (sin encabezados personalizados), y la opción de encabezado de Claude es una beta limitada. La URL personal es, por lo tanto, el único método que funciona en todas las aplicaciones de consumo. La compensación es que la URL es una credencial de portador. Trátela como una contraseña y revoque la clave si se filtra. El servidor nunca repite la clave en una respuesta, redirección o error. Use el encabezado siempre que el cliente admita uno.
| Sin clave | Permitido. El llamante es gratuito con authenticated: false y obtiene exactamente lo que un visitante no conectado ve en el sitio web. |
|---|---|
| Clave válida | El llamante es pro si la cuenta de la clave tiene Pro (de pago o prueba), de lo contrario gratuito. Esto se decide en vivo en cada solicitud, por lo que un plan vencido cae a gratuito de inmediato y una renovación restaura Pro con la misma clave. |
| Clave desconocida / malformada | HTTP 401 con WWW-Authenticate: Bearer. Nunca se degrada silenciosamente a acceso gratuito, por lo que una clave mal escrita falla de manera visible. Los fallos cuentan para el bloqueo de fuerza bruta por IP compartido con la API REST. |
| Clave revocada | HTTP 401, reason: key_revoked |
| Cuenta suspendida | HTTP 403, reason: account_suspended |
Clave sin read:listings | HTTP 403, reason: insufficient_scope |
Niveles de acceso y alcances
Hay un modelo de permisos con dos puertas de entrada. Para los datos del directorio, el servidor MCP usa la regla del propio sitio (canViewFull): los detalles completos son visibles para las cuentas Pro, y para el propietario de un listado en su propio registro. Lo que una página de perfil muestra a todos (el panel de Fuentes, por ejemplo), el conector lo muestra a todos también.
open | Cualquiera, incluso sin clave: search_listings, get_listing, list_categories, list_countries, prepare_listing_submission, compare_listings, list_plans, list_ad_packages, prepare_upgrade, prepare_advertising, prepare_listing_claim, connection_status |
|---|---|
pro | Clave + Pro: get_relationships, get_news, list_jobs, check_domain |
account_read | Clave + Pro + alcance read:account ("asistente de IA — leer mi cuenta") |
account_write | Clave + Pro + alcance write:account ("asistente de IA — actuar por mí") + una confirmación en cada llamada |
| Orden de compuerta | Verificado en este orden: clave → Pro → alcance. El primer fallo devuelve key_required, pro_required (con upgrade_tool: "prepare_upgrade") o scope_required (con required_scope). |
| Alcances opcionales | read:account y write:account no están en los valores predeterminados de una clave nueva. El miembro los marca al crear la clave, o más tarde bajo los Alcances de la clave. Los cambios se aplican en la siguiente llamada. |
Campos solo Pro en get_listing | website, email, phone, social_links, key_people, timeline, technology. Se omiten del perfil básico y se nombran en access.locked_fields, exactamente como la página de perfil los oculta. |
| Nunca disponible | Datos de otros miembros de cualquier tipo; pagos y facturas; datos de administración y moderación; registros no aprobados (pendientes o rechazados) en las herramientas de directorio, y trabajos o relaciones que les pertenezcan. Las herramientas de cuenta solo ven los listados, clientes potenciales, notificaciones, lista de seguimiento y tickets del propietario de la clave. |
Protocolo de confirmación
Cada herramienta account_write toma un confirmation_token opcional y se ejecuta en dos pasos:
- Preparar. Llame sin un token. El servidor valida todo y no escribe nada. Devuelve
{"status":"no_change","message":…}(ya en ese estado) o: { "status": "confirmation_required", "action": "reply_to_lead", "action_summary": "Enviar esta respuesta a Wanjiku Buyer en la conversación #12 (Boss Co): “Felices de demostrar el martes.”", "details": { … }, "confirmation_token": "…", "expires_in_seconds": 600, "instructions": "Aún no se ha hecho nada. Muestre action_summary al usuario … Nunca confirme en su nombre." } - Preguntar. El asistente muestra
action_summaryal usuario y espera un sí claro. - Confirmar. Llame de nuevo con los mismos argumentos más
confirmation_token. El servidor revalida contra el estado actual, consume el token, ejecuta la acción a través del mismo código que el panel y devuelve el resultado con"status": "done".
| Vinculación de token | Firmado con HMAC y vinculado a la clave API, el usuario, el nombre de la herramienta y un hash de los argumentos exactos. Es válido durante 10 minutos y de un solo uso: se consume incluso si la acción luego falla. |
|---|---|
| Fallos | confirmation_invalid con reason: invalid (malformado o falsificado), expired, mismatch (otra herramienta, clave o usuario), args_changed (los argumentos difieren de los confirmados) o used. No se hace nada en ninguno de estos casos. |
| Por qué tokens | Un modelo no puede omitir el paso de preparación, alterar un mensaje después de que el usuario lo apruebe, o reproducir una aprobación para varias acciones. Los avisos de aprobación propios de los clientes (impulsados por las anotaciones) son una segunda capa independiente. |
Enlaces de pago
prepare_upgrade y prepare_advertising devuelven checkout_url: un enlace firmado a /go/checkout/<token> que dice para quién se hizo y qué compra. No cobran nada, no crean nada y nunca ven datos de tarjeta. Ninguna herramienta puede confirmar o completar una compra.
GET el enlace | Una página de revisión (plan o paquete, precio, listado, cuenta). No cambia nada, por lo que las vistas previas de enlaces en aplicaciones de chat son inofensivas. No conectado → 302 a /login?next=…. Conectado como una cuenta diferente, o un token manipulado → 409, sin cobrar nada. |
|---|---|
POST (el botón del miembro) | Requiere el token CSRF de la sesión, repite cada verificación contra la cuenta conectada, registra la intención de pago exactamente como los botones del propio panel (las mismas referencias FLPRO- / FLAD- que coinciden los webhooks), y luego entrega al pago alojado existente de Lemon Squeezy. |
| Vigencia | 24 horas. También detrás del interruptor de mantenimiento de pagos. |
| Sin clave | Devuelve status: "sign_in_needed" con la página de precios o publicidad en lugar de un enlace personal. |
| Guía del modelo | Cada resultado lleva una nota: si el usuario dice "sí, hazlo", dele el enlace de nuevo. Nunca afirme que una compra está hecha. |
Formato de resultados
Cada resultado exitoso de herramienta tiene un resumen de una línea más la carga útil JSON en content[0].text, y la misma carga útil como structuredContent. Los errores que el asistente debe explicar (no encontrado, permiso, entrada inválida, problemas de confirmación) son resultados de herramienta con isError: true y structuredContent.error = { code, message, … }, nunca fallos de protocolo.
pro_required{ "isError": true, "structuredContent": { "error": { "code": "pro_required", "message": "Obtener noticias es una característica Pro de FirmLedger, y la cuenta detrás de esta clave API no está en Pro. …", "tier": "free", "upgrade_url": "…/pricing", "upgrade_tool": "prepare_upgrade", "setup_guide_url": "…/docs/mcp" } } }
Herramientas
Esta lista se genera a partir de las definiciones de herramientas en vivo del servidor, por lo que no puede desviarse de lo que el servidor ofrece. Un argumento de listado acepta un slug (mejor), un nombre exacto, un ID de FirmLedger como FL-00012, o una URL de perfil. Varias coincidencias de nombre exacto devuelven ambiguous con candidatos. Sin coincidencia devuelve not_found, con cualquier registro de nombre similar etiquetado como registros diferentes.
Herramientas abiertas abierto
No se necesita clave. Con una clave respetan el nivel del llamante, por ejemplo, get_listing agrega los campos Pro para Pro.
get_listing Abierta · sin clave
Obtener un perfil de empresa de FirmLedger. El perfil público de FirmLedger de una empresa: descripción, categoría, ubicación, estado de verificación (marca, cómo se probó la propiedad, cuándo se verificó por última vez), puntuaciones de confianza y salud, fuentes, titulares de noticias moderados recientes y el recuento de trabajos abiertos. Con FirmLedger Pro también incluye sitio web, correo electrónico, teléfono, enlaces sociales, personas clave, cronología y tecnología — la misma línea que dibuja el sitio web.
listing * | string (≤ 300 caracteres) La empresa: su slug de FirmLedger (mejor — devuelto por search_listings), su nombre exacto, su ID de FirmLedger como "FL-00012", o su URL de perfil de FirmLedger. |
|---|
list_countries Abierta · sin clave
Listar países en FirmLedger. Los países presentes en el directorio de FirmLedger, cada uno con su número de listados aprobados.
Sin argumentos.
prepare_listing_submission Abierta · sin clave
Preparar un enlace de envío de listado de FirmLedger. NO crea nada. Devuelve un enlace al formulario real de envío de FirmLedger con el nombre de la empresa, el sitio web y (opcionalmente) la categoría, el país y la ciudad prellenados. El usuario lo abre, inicia sesión, completa los campos restantes, revisa todo y lo envía él mismo. También informa si la empresa ya está listada, para que nada se envíe dos veces.
name * | string (≤ 120 caracteres) Nombre de la empresa. |
|---|---|
website | string (≤ 200 caracteres) Sitio web de la empresa, p. ej. "example.co.ke". |
category | string (≤ 60 caracteres) Categoría opcional. |
country | string (≤ 60 caracteres) País opcional. |
city | string (≤ 80 caracteres) Ciudad opcional. |
compare_listings Abierto · sin clave
Compara listados de FirmLedger lado a lado. Compara de 2 a 4 empresas aprobadas de FirmLedger lado a lado: tipo de entidad, categoría, ubicación, año de fundación, tamaño del equipo, sitio web, eslogan, fecha de registro, propiedad, tick, confianza y estado de patrocinio — las mismas filas que la página de comparación de FirmLedger. Úsalo después de search_listings cuando el usuario quiera sopesar empresas entre sí.
listings * | string[] (2–4 elementos) De 2 a 4 empresas (los slugs son los mejores). |
|---|
list_plans Abierto · sin clave
Lista los planes Pro de FirmLedger. Las ofertas actuales de FirmLedger Pro con precio, facturación y duración. Con una clave API también indica si esta cuenta ya está en Pro y si hay una prueba gratuita disponible. Úsalo antes de prepare_upgrade.
Sin argumentos.
prepare_upgrade Abierto · sin clave
Prepara un enlace de pago de FirmLedger Pro. NO cobra nada. Devuelve un enlace personal al proceso de pago propio de FirmLedger para el plan Pro elegido (opcionalmente con un código promocional). El usuario lo abre, inicia sesión, revisa el pedido en FirmLedger y paga él mismo en el proceso de pago seguro de Lemon Squeezy. Nunca puedes completar ni confirmar un pago y nunca debes pedir datos de tarjeta; si el usuario dice "sí, hazlo", dale el enlace de nuevo. Sin una clave API, devuelve la página de precios en su lugar.
plan | string (≤ 120 caracteres) El id del plan de list_plans (o su nombre exacto). |
|---|---|
promo_code | string (≤ 40 caracteres) Código promocional opcional que el usuario te haya dado. |
prepare_listing_claim Abierto · sin clave
Prepara una reclamación de propiedad de un listado. Gratis. Prepara un enlace para reclamar un listado aprobado mediante TXT de DNS, etiqueta meta HTML o insignia del sitio. No crea nada y nunca otorga propiedad. El usuario inicia sesión, genera un token, instala la prueba en el dominio de la empresa y la verifica en FirmLedger.
listing * | string (≤ 300 caracteres) La empresa: su slug de FirmLedger (mejor — devuelto por search_listings), su nombre exacto, su ID de FirmLedger como "FL-00012", o su URL de perfil de FirmLedger. |
|---|---|
method | "dns" | "meta" | "badge" |
connection_status Abierto · sin clave
Comprueba el acceso de conexión de FirmLedger. Informa de lo que puede hacer esta conexión de FirmLedger: acceso gratuito o Pro, autenticación y estado de prueba gratuita activa, y qué herramientas y campos están disponibles. Úsalo cuando el usuario pregunte por qué algo está bloqueado.
Sin argumentos.
Herramientas del directorio Pro pro
Se necesita una clave cuya cuenta tenga Pro (de pago o prueba).
get_relationships PRO
Obtén el grafo de relaciones de una empresa (Pro). FirmLedger Pro. El grafo de relaciones registrado de una empresa: fundadores, inversores, empresas matrices, subsidiarias, productos, servicios y socios — además de las aristas inversas (empresas que fundó o en las que invirtió). Solo relaciones registradas por el propietario verificado o moderadores; no se infiere nada.
listing * | string (≤ 300 caracteres) La empresa: su slug de FirmLedger (mejor — devuelto por search_listings), su nombre exacto, su ID de FirmLedger como "FL-00012", o su URL de perfil de FirmLedger. |
|---|
get_news PRO
Obtén noticias de empresa moderadas (Pro). FirmLedger Pro. Titulares de noticias moderadas recientes sobre una empresa con fechas, editores y enlaces — las mismas historias filtradas por precisión que se muestran en el panel de noticias del perfil.
listing * | string (≤ 300 caracteres) La empresa: su slug de FirmLedger (mejor — devuelto por search_listings), su nombre exacto, su ID de FirmLedger como "FL-00012", o su URL de perfil de FirmLedger. |
|---|---|
limit | any (predeterminado 10) Historias a devolver (1-12). Entero o cadena numérica, limitado a 1–12. |
list_jobs PRO
Lista empleos abiertos (Pro). FirmLedger Pro. Puestos abiertos en empresas aprobadas de FirmLedger, filtrados por empresa y/o ubicación y palabra clave: título, empresa, ubicación, fecha de publicación y dónde postularse. Los empleos en listados no aprobados nunca aparecen.
company | string (≤ 300 caracteres) Empresa opcional (slug, nombre exacto, ID de FirmLedger o URL de perfil). |
|---|---|
location | string (≤ 80 caracteres) Ubicación opcional, p. ej. "Nairobi" o "Kenya" o "Remoto". |
query | string (≤ 80 caracteres) Palabra clave opcional en el título o la descripción del empleo. |
limit | any (predeterminado 10) límite. Entero o cadena numérica, limitado a 1–25. |
offset | any (predeterminado 0) desplazamiento. Entero o cadena numérica, limitado a 0–10000. |
check_domain PRO
Comprueba si un sitio web está listado (Pro). FirmLedger Pro. Dado un dominio o URL de sitio web, informa si un registro aprobado de FirmLedger lo usa y devuelve ese registro — útil para preguntas como "¿es legítimo este sitio?".
domain * | string (≤ 200 caracteres) Un dominio como "example.co.ke" o una URL completa. |
|---|
Lecturas de cuenta account_read
Se necesita una clave + Pro + el alcance opcional read:account. Solo devuelve los datos propios del propietario de la clave.
get_my_listings PRO read:account
Lista mis listados de FirmLedger. Los listados que esta cuenta posee o ha enviado, con estado de moderación, tick, puntuaciones, ventajas Pro, patrocinio, empleos y recuentos de nuevos clientes potenciales. Úsalo primero cuando el usuario se refiera a "mi listado".
Sin argumentos.
get_analytics PRO read:account
Lee mis analíticas de audiencia. Analíticas de audiencia para los listados propios del usuario — vistas hoy/7/30 días/total, visitantes únicos, clics en perfil y sitio web, clientes potenciales, el embudo de 30 días, las principales ubicaciones de visitantes y vistas por listado. Los mismos números que Panel → Analíticas de audiencia.
listing | string (≤ 300 caracteres) Opcional: uno de los listados del usuario. Omítelo para todos combinados. |
|---|
list_leads PRO read:account
Lista mis clientes potenciales. La bandeja de entrada de FirmLedger Leads del usuario: consultas recibidas en sus listados (carpeta "recibidos", la predeterminada), archivadas ("archivados") o consultas que envió a otras empresas ("enviados"). Filtra por estado o listado; paginado.
box | "received" | "archived" | "sent" |
|---|---|
status | "new" | "contacted" | "qualified" | "won" | "lost" |
listing | string (≤ 300 caracteres) Opcional: solo clientes potenciales para este listado del usuario. |
limit | integer (mín 1 · máx 50 · predeterminado 20) |
page | integer (mín 1 · predeterminado 1) |
get_lead PRO read:account
Lee una conversación de cliente potencial. Una conversación de la bandeja de entrada de Leads con los detalles del solicitante y cada mensaje, del más antiguo al más reciente. Úsalo antes de reply_to_lead para que la respuesta encaje en el hilo.
lead_id * | integer (mín 1) lead_id de list_leads. |
|---|
get_watchlist PRO read:account
Lee mi lista de seguimiento. Las empresas que el usuario sigue en FirmLedger, de la más reciente a la más antigua.
Sin argumentos.
export_watchlist_csv PRO read:account
Exporta mi lista de seguimiento como CSV. La lista de seguimiento del usuario como texto CSV (nombre, categoría, tipo, ubicación, datos de contacto, pila tecnológica, propietario verificado, confianza, seguido desde) — el mismo archivo que el botón Exportar del panel.
Sin argumentos.
get_notifications PRO read:account
Lee mis notificaciones. Las notificaciones en la aplicación de FirmLedger del usuario, de la más reciente a la más antigua, con el recuento de no leídas. Establece unread_only para solo las no leídas.
unread_only | boolean (predeterminado false) |
|---|---|
limit | integer (mín 1 · máx 60 · predeterminado 20) |
list_my_tickets PRO read:account
Lee mis tickets de soporte. Los tickets de soporte de FirmLedger del usuario. Pasa una referencia de ticket para leer la conversación completa de ese ticket.
ticket | string (≤ 40 caracteres) Referencia de ticket opcional, p. ej. "TK-1A2B3C". |
|---|
get_api_status PRO read:account
Estado de la API REST v1 para esta clave. El estado de la API REST de FirmLedger para esta cuenta y clave API, tal como lo responden /api/v1/me y /api/v1/usage: identidad, plan y estado de prueba gratuita, los alcances de la clave, presupuestos en vivo por minuto de lectura/escritura, agregados de uso duraderos y el catálogo de endpoints. También indica claramente que el conector MCP y la API REST v1 son la misma plataforma API — una cuenta, una clave, un derecho Pro — y exactamente qué sucede con el acceso a API y MCP cuando termina una prueba gratuita.
key_prefix | string (≤ 40 caracteres) Opcional: enfócate en una clave por su prefijo. |
|---|
list_webhooks PRO read:account
Lista mis destinos de webhook. Los destinos de webhook de la cuenta con eventos, filtros de categoría, estado activo y prefijo del secreto de firma — además de entregas recientes (estado, código HTTP, intentos, último error) cuando se proporciona un id de webhook.
webhook_id | integer (mín 1) Opcional: un destino, con sus entregas recientes. |
|---|---|
limit | integer (mín 1 · máx 25 · predeterminado 10) |
list_api_keys PRO read:account
Lista mis claves API. Las claves API de la cuenta con etiqueta, prefijo, alcances, totales de uso y último uso — nunca una clave en bruto. Úsalo para nombrar una clave antes de revocarla o cambiarle los alcances.
Sin argumentos.
Cambios de cuenta account_write
Se necesita una clave + Pro + el alcance opcional write:account, y el apretón de manos de confirmación en cada llamada.
start_lead PRO write:account · confirma
Contacta con una empresa reclamada. Inicia una nueva conversación de FirmLedger Leads con otra empresa aprobada y reclamada. El correo del miembro con sesión iniciada se usa automáticamente, el correo de la empresa permanece privado y el propietario recibe una notificación en su bandeja de entrada de Leads. Requiere la confirmación del usuario de la consulta exacta.
listing * | string (≤ 300 caracteres) La empresa: su slug de FirmLedger (mejor — devuelto por search_listings), su nombre exacto, su ID de FirmLedger como "FL-00012", o su URL de perfil de FirmLedger. |
|---|---|
name | string (≤ 120 caracteres) Nombre del remitente opcional; por defecto, el nombre del perfil del miembro. |
phone | string (≤ 40 caracteres) |
looking_for | string (≤ 140 caracteres) Asunto corto opcional o lo que el miembro necesita. |
message * | string (≤ 4000 caracteres) |
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, llama de nuevo con los MISMOS argumentos más este token. |
reply_to_lead PRO write:account · confirma
Responde a un cliente potencial. Envía una respuesta en una de las conversaciones de clientes potenciales del usuario, exactamente como hace el cuadro Responder en el sitio web (la otra parte recibe una notificación). Requiere la confirmación del usuario: la primera llamada devuelve el mensaje exacto para que lo apruebe.
lead_id * | integer (mín 1) |
|---|---|
message * | string (≤ 4000 caracteres) El texto de la respuesta, escrito o aprobado por el usuario. |
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, llama de nuevo con los MISMOS argumentos más este token. |
set_lead_status PRO write:account · confirma
Cambia el estado de un cliente potencial. Mueve un cliente potencial en la bandeja de entrada de negocios del usuario a nuevo, contactado, calificado, ganado o perdido. Requiere la confirmación del usuario.
lead_id * | integer (mín. 1) |
|---|---|
status * | "new" | "contacted" | "qualified" | "won" | "lost" |
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, vuelve a llamar con los MISMOS argumentos más este token. |
watchlist_add PRO write:account · confirma
Añadir una empresa a mi lista de seguimiento. Añade una empresa aprobada a la lista de seguimiento del usuario para que reciba notificaciones cuando cambie su registro. Requiere la confirmación del usuario.
listing * | string (≤ 300 caracteres) La empresa: su slug de FirmLedger (mejor — devuelto por search_listings), su nombre exacto, su ID de FirmLedger como "FL-00012", o su URL de perfil de FirmLedger. |
|---|---|
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, vuelve a llamar con los MISMOS argumentos más este token. |
watchlist_remove PRO write:account · confirma
Eliminar una empresa de mi lista de seguimiento. Elimina una empresa de la lista de seguimiento del usuario. Requiere la confirmación del usuario.
listing * | string (≤ 300 caracteres) La empresa: su slug de FirmLedger (mejor — devuelto por search_listings), su nombre exacto, su ID de FirmLedger como "FL-00012", o su URL de perfil de FirmLedger. |
|---|---|
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, vuelve a llamar con los MISMOS argumentos más este token. |
create_support_ticket PRO write:account · confirma
Abrir un ticket de soporte. Abre un ticket de soporte de FirmLedger para el usuario. Categorías: facturación, técnico, listado, cuenta, verificación, otro. Requiere la confirmación del usuario sobre el asunto y el mensaje exactos.
subject * | string (≤ 200 caracteres) |
|---|---|
category * | "billing" | "technical" | "listing" | "account" | "verification" | "other" |
body * | string (≤ 5000 caracteres) El problema en unas pocas frases. |
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, vuelve a llamar con los MISMOS argumentos más este token. |
manage_job PRO write:account · confirma
Editar, cerrar o eliminar mi empleo. Gestiona un empleo propiedad del miembro: edita su título, tipo, ubicación, enlace de solicitud o descripción, ciérralo o elimínalo permanentemente. Editar un rol activo o cerrado lo devuelve a moderación antes de que vuelva a ser público. Requiere la confirmación del usuario.
action * | "edit" | "close" | "remove" | "delete" |
|---|---|
job_id * | integer (mín. 1) |
title | string (≤ 80 caracteres) |
role_type | "Full-time" | "Part-time" | "Contract" | "Internship" | "Remote" |
location | string (≤ 80 caracteres) |
apply_url | string (≤ 400 caracteres) |
description | string (≤ 600 caracteres) |
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, vuelve a llamar con los MISMOS argumentos más este token. |
post_job PRO write:account · confirma
Publicar un empleo en mi listado. Envía una oferta de empleo en uno de los listados del usuario (el listado necesita beneficios Pro activos; hasta 5 roles abiertos o pendientes). Como el formulario del panel, pasa primero por moderación y se publica después de la aprobación. Requiere la confirmación del usuario.
listing * | string (≤ 300 caracteres) Uno de los listados propios del usuario. |
|---|---|
title * | string (≤ 80 caracteres) |
role_type | "Full-time" | "Part-time" | "Contract" | "Internship" | "Remote" |
location * | string (≤ 80 caracteres) Ciudad, o "Remoto". |
apply_url * | string (≤ 400 caracteres) Enlace https:// completo a la oferta de empleo o página de carreras. |
description * | string (≤ 600 caracteres) |
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, vuelve a llamar con los MISMOS argumentos más este token. |
mark_notifications_read PRO write:account · confirma
Marcar notificaciones como leídas. Marca una notificación (notification_id) o todas ellas (all: true) como leídas. Requiere la confirmación del usuario.
notification_id | integer (mín. 1) |
|---|---|
all | boolean |
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, vuelve a llamar con los MISMOS argumentos más este token. |
refresh_listing_scores PRO write:account · confirma
Actualizar las puntuaciones de mi listado. Recalcula las puntuaciones de confianza, salud y completitud de uno de los listados del usuario a partir de su registro actual — el "Realinear puntuaciones" del panel. Requiere la confirmación del usuario.
listing * | string (≤ 300 caracteres) Uno de los listados propios del usuario. |
|---|---|
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, vuelve a llamar con los MISMOS argumentos más este token. |
refresh_listing_tech PRO write:account · confirma
Actualizar la instantánea tecnológica de mi listado. Escanea el sitio web de uno de los listados del usuario y actualiza su instantánea tecnológica — el "Actualizar tecnología" del panel. Requiere la confirmación del usuario.
listing * | string (≤ 300 caracteres) Uno de los listados propios del usuario. |
|---|---|
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, vuelve a llamar con los MISMOS argumentos más este token. |
refresh_listing_news PRO write:account · confirma
Actualizar las noticias de mi listado. Busca nueva cobertura de uno de los listados aprobados del usuario con las mismas reglas de precisión y moderación que el "Actualizar noticias" del panel (una vez por minuto por listado). Requiere la confirmación del usuario.
listing * | string (≤ 300 caracteres) Uno de los listados aprobados propios del usuario. |
|---|---|
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, vuelve a llamar con los MISMOS argumentos más este token. |
request_listing_removal PRO write:account · confirma
Solicitar la eliminación de mi listado. Envía una solicitud de eliminación para un listado que el usuario posee o envió originalmente. Un moderador la revisa; nada se elimina hasta que la acepte. Requiere la confirmación del usuario.
listing * | string (≤ 300 caracteres) Un listado que el usuario posee o envió. |
|---|---|
reason * | string (≤ 2000 caracteres) Por qué debería eliminarse (20+ caracteres). |
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, vuelve a llamar con los MISMOS argumentos más este token. |
create_webhook PRO write:account · confirma
Crear un destino de webhook. Registra un webhook en la cuenta del usuario después de la confirmación explícita. Los eventos de listado se enviarán a esta URL. Requiere Pro (incluida una prueba gratuita) y write:account. El secreto de firma se devuelve solo una vez; mantenlo privado.
url * | string (≤ 500 caracteres) Destino HTTPS público para eventos firmados. |
|---|---|
label | string (≤ 80 caracteres) |
events * | string[] (1–6 elementos) |
categories | string[] |
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, vuelve a llamar con los MISMOS argumentos más este token. |
reply_to_ticket PRO write:account · confirma
Responder a un ticket de soporte abierto. Envía una respuesta en uno de los tickets de soporte propios del usuario — el mismo hilo que muestra el panel y el mismo mensaje que responde un agente. Los tickets cerrados no pueden recibir respuestas. Requiere la confirmación del usuario sobre el texto exacto.
ticket * | string (≤ 40 caracteres) La referencia del ticket (p. ej. TK-1A2B3C) o su id, de list_my_tickets. |
|---|---|
message * | string (≤ 4000 caracteres) El texto de la respuesta, escrito o aprobado por el usuario. |
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, vuelve a llamar con los MISMOS argumentos más este token. |
manage_webhooks PRO write:account · confirma
Gestionar mis destinos de webhook. Crea, actualiza, pausa, reanuda, rota el secreto de firma de, prueba, reintenta una entrega para, o elimina un destino de webhook en la cuenta del usuario — las mismas operaciones que Panel → API de desarrollador. Los secretos solo se devuelven para crear y rotar. Requiere la confirmación del usuario.
action * | "create" | "update" | "pause" | "resume" | "rotate_secret" | "test" | "retry_delivery" | "delete" |
|---|---|
webhook_id | integer (mín. 1) Requerido para cada acción excepto crear. |
url | string (≤ 500 caracteres) crear/actualizar: la URL del receptor (https en producción). |
label | string (≤ 80 caracteres) |
events | string[] crear/actualizar: tipos de eventos a los que suscribirse. |
categories | string[] |
delivery_id | integer (mín. 1) retry_delivery: qué entrega reintentar. |
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, vuelve a llamar con los MISMOS argumentos más este token. |
manage_api_keys PRO write:account · confirma
Gestionar mis claves API. Crea una clave API (la clave cruda se devuelve una vez), revoca una clave o cambia los alcances de una clave — los controles de API de desarrollador del panel. Requiere la confirmación del usuario. Las claves también pueden llevar los alcances de asistente de IA (read:account / write:account) que usa este conector.
action * | "create" | "revoke" | "update_scopes" |
|---|---|
label | string (≤ 60 caracteres) crear: un nombre para la clave. |
scopes | string[] (1–9 elementos) IDs de alcance. Requeridos para update_scopes; crear usa por defecto los alcances estándar. |
key_id | integer (mín. 1) revocar/update_scopes: el id de clave de list_api_keys. |
key_prefix | string (≤ 40 caracteres) Alternativa opcional a key_id. |
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, vuelve a llamar con los MISMOS argumentos más este token. |
update_my_listing PRO write:account · confirma
Editar uno de mis listados. Cambia campos en un listado que el usuario posee (nombre, eslogan, descripción, sitio web, correo electrónico, teléfono, país, ciudad, región, dirección, logo_url, fundado, tamaño, etiquetas, redes sociales) — el mismo servicio que usan el formulario de edición del panel y PUT /api/v1/my/listings/:id, incluida la regla de re-moderación cuando el registro principal cambia. Requiere la confirmación del usuario.
listing * | string (≤ 300 caracteres) La empresa: su slug de FirmLedger (el mejor — devuelto por search_listings), su nombre exacto, su ID de FirmLedger como "FL-00012", o su URL de perfil de FirmLedger. |
|---|---|
name | string (≤ 120 caracteres) |
tagline | string (≤ 160 caracteres) |
description | string (≤ 4000 caracteres) |
website | string (≤ 300 caracteres) |
email | string (≤ 190 caracteres) |
phone | string (≤ 40 caracteres) |
country | string (≤ 80 caracteres) |
city | string (≤ 80 caracteres) |
region | string (≤ 80 caracteres) |
address | string (≤ 200 caracteres) |
logo_url | string (≤ 500 caracteres) |
founded | string (≤ 12 caracteres) |
size | string (≤ 40 caracteres) |
tags | string (≤ 300 caracteres) |
socials | any Enlaces de perfiles sociales claveados por red; usa un objeto vacío para limpiar. También se acepta una cadena JSON. |
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, llama de nuevo con los MISMOS argumentos más este token. |
manage_lead PRO write:account · confirmaciones
Archiva, restaura o elimina una conversación de lead. Archiva una conversación fuera de la bandeja de entrada del negocio, restáurala o elimínala permanentemente — los controles de conversación del panel. Requiere la confirmación del usuario (eliminar es irreversible).
action * | "archive" | "unarchive" | "delete" |
|---|---|
lead_id * | integer (mín 1) El id del lead de list_leads. |
confirmation_token | string (≤ 2048 caracteres) Déjalo vacío en la primera llamada: recibes un action_summary y un token en lugar de la acción. Después de que el usuario confirme explícitamente ese resumen, llama de nuevo con los MISMOS argumentos más este token. |
Errores
Errores de herramienta (isError: true, HTTP 200)
not_found | No hay un registro aprobado (o ninguno tuyo) que coincida. Incluye did_you_mean (registros diferentes, claramente etiquetados) y, para empresas, una pista para usar prepare_listing_submission. Nunca se responde con datos inventados. |
|---|---|
ambiguous | Varios registros comparten ese nombre exacto. Incluye candidates, así que llama de nuevo con un slug. |
key_required | Se llamó a una herramienta de cuenta sin clave API. Incluye create_key_url. |
pro_required | La herramienta o acción requiere Pro. Incluye tier, upgrade_url, upgrade_tool: "prepare_upgrade" y, cuando sea elegible, free_trial_url. |
scope_required | La clave carece de read:account / write:account. Incluye required_scope y manage_keys_url. |
confirmation_invalid | Consulta el apretón de manos de confirmación. reason es uno de invalid, expired, mismatch, args_changed o used. |
not_approved | La acción necesita un listado aprobado (p. ej., publicidad, publicar un empleo) y este está pendiente o rechazado. |
limit_reached | Se alcanzó una regla del sitio, p. ej., máximo 5 posiciones abiertas por listado. |
payments_unavailable · payments_paused · checkout_unavailable | El pago en línea no está configurado, está en mantenimiento, o el plan o paquete no está conectado al pago. No se preparó ningún enlace. |
promo_invalid | El código promocional pasado a prepare_upgrade no se puede aplicar. No se preparó ningún enlace. |
upstream_unavailable | Una actualización confirmada (noticias o tecnología) no pudo alcanzar su fuente. Es seguro intentarlo más tarde. |
invalid_input | Falta un argumento requerido o está malformado. El mensaje, y errors cuando esté presente, indican cuál. |
unknown_tool | No hay ninguna herramienta con ese nombre. Incluye available_tools. |
internal_error | Un fallo inesperado (registrado en el servidor). No se cambió nada más. Es seguro reintentar. |
Errores HTTP (cuerpo de error JSON-RPC)
401 | Clave desconocida, malformada o revocada (reason: invalid_key / key_revoked). JSON-RPC -32001. |
|---|---|
403 | account_suspended (-32004) o insufficient_scope para read:listings (-32005) |
405 | GET / DELETE: el servidor no tiene estado |
429 | Límite de tasa o límite de escritura confirmada (-32006), o el bloqueo por dirección después de claves incorrectas repetidas (-32003). Incluye Retry-After. |
503 | El área de la API está en mantenimiento (-32002). Incluye Retry-After. |
400 / 404 | El cuerpo no es JSON-RPC (-32700), o una ruta distinta de /mcp o /mcp/<key> (-32601) |
Límites
| Con una clave | 60 llamadas de herramienta por minuto por clave: el mismo presupuesto de lectura por clave en vivo que la API REST, en un cubo separado. initialize y tools/list son gratuitos. |
|---|---|
| Cambios confirmados | Una llamada de cambio de cuenta con un confirmation_token también se carga al presupuesto de escritura de la clave: 20 por minuto, igual que las escrituras REST. Las llamadas de preparación (sin token) son llamadas ordinarias. |
| Sin clave | 120 llamadas de herramienta por minuto por dirección de cliente |
| Tamaños de página | search_listings ≤ 25 (predeterminado 10) · list_jobs ≤ 25 (predeterminado 10) · get_news ≤ 12 · desplazamientos ≤ 10000. Los valores fuera de rango se ajustan, y la respuesta informa el limit realmente usado. |
| Paginación | Las respuestas de lista llevan total (exacto), count, offset, has_more y next_offset. |
| Contadores de uso | Las llamadas MCP no se agregan a tus estadísticas de uso REST. |
Semántica de conexión y acción
connection_status devuelve tier (free/pro), authenticated, access_source (free/free_trial/paid_pro), trial_active, trial_expires_at y access_expires_at. Una conexión sin clave no puede identificar la prueba de un miembro. Los alcances de cuenta siguen siendo requeridos durante las pruebas.
prepare_listing_claim no escribe nada, acepta dns/meta/badge y enlaza al formulario de verificación de propiedad. create_webhook usa la validación de URL pública, firma, cola de entrega y límites del servicio webhook compartido. Crear un destino requiere confirmación explícita y devuelve un secreto de firma una sola vez; no envía un evento de prueba. Las solicitudes de eliminación siguen sujetas a verificaciones de propiedad y moderación.
FirmLedger no tiene flujo OAuth de Vercel. Un desafío de inicio de sesión de Vercel indica configuración del conector o una restricción de despliegue ascendente a investigar; no agregues metadatos de descubrimiento OAuth ni deshabilites las verificaciones de clave inválida para ocultarlo. El MCP de producción debe ser accesible sin un inicio de sesión del proveedor de hosting.
Garantías de seguridad
- Las herramientas de directorio son de solo lectura a nivel de base de datos. Consultan a través de una conexión SQLite separada abierta
readonly. Una escritura a través de ella falla conSQLITE_READONLY. - Las lecturas de cuenta no escriben nada, ni siquiera "marcar como leído". Marcar notificaciones como leídas es su propia acción confirmada.
- Los cambios de cuenta reutilizan el código del panel (las mismas validaciones, límites, notificaciones y moderación), así que el conector no puede hacer nada que el miembro no pudiera hacer en el sitio web. No puede editar, eliminar ni reclamar listados, y la eliminación es una solicitud que un moderador revisa.
- Los enlaces de pago no crean nada hasta que el miembro presiona el botón en FirmLedger mismo, con sesión iniciada, con un token CSRF.
prepare_listing_submissionsolo construye un enlace a/dashboard/listings/newcon los campos prellenados.- El conjunto de pruebas (
npm run test:mcp) toma la huella de cada tabla relevante antes y después de ejercitar cada herramienta de lectura y cada paso de preparación, y falla ante cualquier diferencia. Luego verifica que cada acción confirmada cambie exactamente lo que describió.
Ejemplos en bruto
searchcurl -s https://mcp.firmledger.co.ke/mcp \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -H "Authorization: Bearer fl_live_your_key" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_listings","arguments":{"category":"Fintech","city":"Nairobi","verified_only":true,"limit":5}}}'
prepara, luego confirma# 1. prepara: devuelve action_summary + confirmation_token, no cambia nada {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"watchlist_add","arguments":{"listing":"kilimo-soft"}}} # 2. después de que el usuario diga sí: mismos argumentos + el token {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"watchlist_add","arguments":{"listing":"kilimo-soft","confirmation_token":"…"}}}
Los clientes SDK hacen el apretón de manos initialize por ti. El servidor sin estado también responde a un tools/call simple, como arriba.