Saltar al contenido principal
Agrega firmas electrónicas legalmente vinculantes a cualquier agente, conversación o flujo de trabajo Vibe de Mistral registrando el servidor MCP de Firma como un Conector. Firma expone su API como un servidor MCP, lo que significa que un agente de Mistral puede enviar solicitudes de firma, listar plantillas y consultar el estado de firma como llamadas nativas a herramientas. Esta guía cubre tres rutas de integración:
  1. Registrar Firma como Conector - El patrón nativo de Mistral. Registra el servidor MCP de Firma una vez y luego úsalo en conversaciones, agentes y Vibe. Ideal para la mayoría de los casos de uso.
  2. Function calling con la Chat Completions API - Define las operaciones de Firma como herramientas manualmente. Ideal cuando quieres control total sobre el esquema de la herramienta o aún no usas Conectores.
  3. Conector personalizado (autenticación inline) - Pasa la URL del servidor MCP de Firma y la clave API en el momento de la conversación sin registrarla previamente. Útil para configuraciones multi-tenant donde cada usuario tiene su propia clave de Firma.

Requisitos previos

  • Una cuenta de Firma con una clave API
  • Una cuenta de Mistral con acceso API a Studio (https://console.mistral.ai)
  • Al menos una plantilla de Firma con campos de firma configurados
  • El SDK de Python mistralai: pip install mistralai
  • La librería requests (para la Ruta 2): pip install requests
Firma usa la clave API sin procesar como valor del encabezado Authorization. No la antepongas con Bearer. Esto difiere de muchas otras API.

Ruta 1: Registrar Firma como Conector

Esta es la ruta más limpia. Registras el servidor MCP de Firma una vez, y todas las superficies de Mistral - la Conversations API, la Agents API y Vibe - pueden usar las herramientas de Firma de inmediato.

Paso 1: Registrar el Conector

import asyncio
import os
from mistralai.client import Mistral

client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])


async def main() -> None:
    connector = await client.beta.connectors.create_async(
        name="firma",
        description="Send and manage e-signature requests via Firma",
        server="https://mcp.firma.dev/mcp",
        auth_type="api-key",
        auth_value=os.environ["FIRMA_API_KEY"],
    )
    print(f"Connector ID: {connector.id}")


asyncio.run(main())
El Conector queda registrado de forma centralizada en tu espacio de trabajo de Mistral. La clave API de Firma se almacena cifrada y nunca llega al modelo ni al usuario final.
Nunca coloques FIRMA_API_KEY en código del lado del cliente ni la subas a un repositorio. Guárdala en el gestor de secretos de tu plataforma de despliegue y cárgala en tiempo de ejecución.

Paso 2: Usar el Conector en una conversación

Pasa el ID del Conector en el array tools y deja que el modelo decida qué herramienta de Firma llamar:
import asyncio
import os
from mistralai.client import Mistral

client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])


async def main() -> None:
    response = await client.beta.conversations.start_async(
        model="mistral-large-latest",
        inputs=[
            {"role": "user", "content": "Send a signing request for template tmpl_abc123 to Alice Johnson at alice@example.com."}
        ],
        tools=[{"type": "connector", "connector_id": "<firma_connector_id>"}],
    )
    for output in response.outputs:
        if output.type == "message.output":
            print(output.content)


asyncio.run(main())
El modelo inspecciona las herramientas expuestas por el Conector, elige la correcta (p. ej., signing_requests_create_and_send), construye los argumentos a partir del mensaje del usuario y la ejecuta.

Paso 3: Construir un agente de Firma persistente

Para un agente reutilizable que siempre tenga disponibles las herramientas de Firma, créalo una vez y conversa con él más tarde:
import asyncio
import os
from mistralai.client import Mistral

client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])


async def main() -> None:
    agent = await client.beta.agents.create_async(
        name="signing_agent",
        description="Sends and tracks e-signature requests with Firma.",
        model="mistral-large-latest",
        instructions=(
            "You help users send and track signing requests with Firma. "
            "Always confirm signer name and email before calling create_and_send. "
            "After sending, return the signing_request_id so the user can reference it later."
        ),
        tools=[{"type": "connector", "connector_id": "<firma_connector_id>"}],
    )
    print(f"Agent ID: {agent.id}")


asyncio.run(main())
Este mismo agente se puede usar desde Vibe y desde tu propio producto a través de la Conversations API.

Ruta 2: Function calling con la Chat Completions API

Si prefieres definir las herramientas de Firma tú mismo, expónlas como funciones en el endpoint de Chat Completions. Esto funciona en cualquier modelo de Mistral que admita tool calling.
import json
import os
import requests
from mistralai.client import Mistral

FIRMA_API = "https://api.firma.dev/functions/v1/signing-request-api"
mistral = Mistral(api_key=os.environ["MISTRAL_API_KEY"])

tools = [
    {
        "type": "function",
        "function": {
            "name": "create_and_send_signing_request",
            "description": "Create a signing request from a Firma template and send it to a recipient.",
            "parameters": {
                "type": "object",
                "properties": {
                    "template_id": {"type": "string"},
                    "first_name": {"type": "string"},
                    "email": {"type": "string"},
                    "last_name": {"type": "string"},
                },
                "required": ["template_id", "first_name", "email"],
            },
        },
    }
]


def create_and_send_signing_request(template_id, first_name, email, last_name=""):
    response = requests.post(
        f"{FIRMA_API}/signing-requests/create-and-send",
        headers={
            "Authorization": os.environ["FIRMA_API_KEY"],
            "Content-Type": "application/json",
        },
        json={
            "template_id": template_id,
            "recipients": [
                {
                    "first_name": first_name,
                    "last_name": last_name,
                    "email": email,
                    "designation": "Signer",
                    "order": 1,
                }
            ],
        },
    )
    response.raise_for_status()
    return response.json()


messages = [
    {"role": "user", "content": "Send template tmpl_abc123 to Alice Johnson, alice@example.com."}
]

completion = mistral.chat.complete(
    model="mistral-large-latest",
    messages=messages,
    tools=tools,
    tool_choice="auto",
)

tool_call = completion.choices[0].message.tool_calls[0]
args = json.loads(tool_call.function.arguments)
result = create_and_send_signing_request(**args)
print(result)
El endpoint create-and-send crea la solicitud de firma y la envía por correo a los destinatarios en una sola llamada. Solo se requieren first_name y email para cada destinatario. Si quieres un paso de revisión mediado por el modelo antes de enviar, usa POST /signing-requests para crear un borrador, y luego POST /signing-requests/{id}/send por separado.

Ruta 3: Conector personalizado (autenticación inline)

Cuando no quieras pre-registrar un Conector (p. ej., cada usuario tiene su propia clave API de Firma), pasa la URL del servidor MCP y las credenciales de forma inline:
import asyncio
import os
from mistralai.client import Mistral

client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])


async def main() -> None:
    response = await client.beta.conversations.start_async(
        model="mistral-large-latest",
        inputs=[
            {"role": "user", "content": "Send template tmpl_abc123 to Alice at alice@example.com."}
        ],
        tools=[
            {
                "type": "custom-connector",
                "connector_id": "firma",
                "authorization": {
                    "type": "api-key",
                    "value": os.environ["FIRMA_API_KEY"],
                },
                "tool_configuration": {
                    "type": "custom",
                    "url": "https://mcp.firma.dev/mcp",
                },
            }
        ],
    )
    for output in response.outputs:
        if output.type == "message.output":
            print(output.content)


asyncio.run(main())
Esto es útil para configuraciones multi-tenant donde cada cliente tiene un espacio de trabajo de Firma y una clave API independientes.

Integración de webhooks: reaccionar cuando se firman documentos

Firma envía webhooks para cada cambio de estado en una solicitud de firma. El patrón típico con agentes de Mistral es recibir el webhook en tu propio backend y luego actualizar tu base de datos directamente o devolver el evento a un agente para acciones de seguimiento. Handler mínimo en FastAPI:
import os
from fastapi import FastAPI, Request
from mistralai.client import Mistral

app = FastAPI()
mistral = Mistral(api_key=os.environ["MISTRAL_API_KEY"])


@app.post("/webhooks/firma")
async def firma_webhook(request: Request):
    payload = await request.json()
    event_type = payload.get("type")
    data = payload.get("data", {})

    if event_type == "signing_request.completed":
        signing_request_id = data["signing_request"]["id"]
        # Option A: update your database and move on.
        # Option B: hand the event to an agent for follow-up.
        await mistral.beta.conversations.start_async(
            agent_id="<signing_agent_id>",
            inputs=[
                {
                    "role": "user",
                    "content": (
                        f"Signing request {signing_request_id} was just completed. "
                        "Update the deal in our CRM and email the account owner."
                    ),
                }
            ],
        )

    return {"received": True}
Registra el endpoint en Firma en Configuración > Webhooks.
Para uso en producción, verifica las firmas de los webhooks usando el secreto de webhook de tu Firma y HMAC-SHA256. Agrega esta verificación al inicio de tu handler:
import hashlib
import hmac

def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(), payload, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)


@app.post("/webhooks/firma")
async def firma_webhook(request: Request):
    body = await request.body()
    signature = request.headers.get("x-firma-signature", "")
    if not verify_signature(body, signature, os.environ["FIRMA_WEBHOOK_SECRET"]):
        return JSONResponse(status_code=401, content={"error": "invalid signature"})
    payload = json.loads(body)
    # ... handle event
Consulta la guía de webhooks para conocer todos los tipos de eventos y formatos de payload.

Vibe: flujos de trabajo de firma electrónica para usuarios finales

Una vez que el Conector de Firma esté registrado en tu espacio de trabajo de Mistral, los usuarios de Vibe pueden invocar Firma directamente desde el chat. Prompts típicos:
  • “Envía el NDA estándar a alice@example.com.”
  • “¿Cuál es el estado del contrato que envié a Bob ayer?”
  • “Lista todas las solicitudes de firma que sigan pendientes.”
Usa el flujo de aprobación human-in-the-loop de Mistral si quieres que los usuarios finales confirmen antes de que el agente realmente envíe la solicitud. Las solicitudes de firma salientes llegan a terceros; un paso de confirmación vale el turno adicional.

Firma embebida

Si quieres que los firmantes completen documentos dentro de tu propio producto en lugar de abrir la página alojada por Firma, lee el ID del firmante de la respuesta de create-and-send e incrusta la UI de firma en un iframe:
<iframe
  src="https://app.firma.dev/signing/{signing_request_user_id}"
  style="width:100%;height:900px;border:0;"
  allow="camera;microphone;clipboard-write"
  title="Document Signing"
></iframe>
Consulta la guía de firma embebida para la configuración completa, incluidas las mejores prácticas de seguridad.

Docs MCP para asistencia en tiempo de desarrollo

Para el desarrollo dentro de Vibe o cualquier herramienta de codificación compatible con MCP, registra el servidor Docs MCP de Firma en https://docs.firma.dev/mcp como un Conector separado. El Docs MCP expone la búsqueda sobre la documentación completa de Firma, de modo que el modelo pueda responder con precisión preguntas sobre la API mientras escribes código de integración. Esto es para la experiencia de desarrollo y no afecta a tus agentes en ejecución.

Próximos pasos