GitHub Copilot es bueno escribiendo código que parece correcto. El código de integración es donde esto se convierte en un problema. Pídele que conecte una API de firma electrónica e inventará con total seguridad un endpoint, adivinará la forma de una carga útil (payload) o recurrirá a un prefijo Bearer que tu proveedor no utiliza. Terminas depurando al asistente en lugar de lanzar la funcionalidad.
La solución es darle a Copilot el contrato real de la API mientras trabaja. Firma.dev ofrece un servidor Docs MCP y un conjunto de convenciones de repositorio que, juntos, hacen que Copilot genere código de integración correcto a la primera. Dado que Firma.dev es una plataforma de firma electrónica orientada a la API que se factura a 0,049 € por sobre (~5¢ USD) sin licencias de usuario ni mínimos, la integración en sí es pequeña. El objetivo es permitir que Copilot escriba esa pequeña integración de forma correcta en lugar de plausible.
Esto abarca tres pasos de configuración: conectar el Docs MCP, añadir un archivo de instrucciones para todo el repositorio y dar a Copilot los patrones de referencia para que coincidan.
Paso 1: conectar el Docs MCP de Firma.dev
El servidor Docs MCP expone la documentación completa de Firma.dev como herramientas de búsqueda. Al estar conectado, Copilot consulta endpoints reales, formas de solicitud actuales y esquemas de carga útil de webhooks en lugar de adivinar. Es de solo lectura y sin autenticación, por lo que nunca le pasas una clave API.
En VS Code, añádelo a nivel de espacio de trabajo en .vscode/mcp.json:
{
"servers": {
"firma-docs": {
"type": "http",
"url": "https://docs.firma.dev/mcp"
}
}
}{
"servers": {
"firma-docs": {
"type": "http",
"url": "https://docs.firma.dev/mcp"
}
}
}{
"servers": {
"firma-docs": {
"type": "http",
"url": "https://docs.firma.dev/mcp"
}
}
}Recarga la ventana y confirma que firma-docs aparece en el selector de herramientas de Copilot Chat. Para la CLI de Copilot, añade el mismo servidor a ~/.copilot/mcp-config.json y reinicia. En JetBrains o Visual Studio, abre Configuración → Copilot → Servidores MCP y añade un servidor HTTP llamado firma-docs con la URL https://docs.firma.dev/mcp.
Paso 2: añadir un archivo de instrucciones de Copilot para todo el repositorio
.github/copilot-instructions.md se carga automáticamente por Copilot Chat, el agente de codificación y la revisión de código en todos los entornos compatibles. Aquí es donde fijas las convenciones que mantienen el código generado conforme al contrato. Crea o añade al archivo:
## Integración de firma electrónica con Firma.dev
Al generar código que envía, recibe o incrusta firmas electrónicas de Firma, sigue estas convenciones:
- URL base de la API: `https://api.firma.dev/functions/v1/signing-request-api`
- Autorización: encabezado `Authorization` con la clave API bruta de Firma vacía (sin prefijo `Bearer`)
- La clave se encuentra en la variable de entorno `FIRMA_API_KEY`. Llama a Firma únicamente desde el backend, nunca desde el navegador. No confirmes nunca el valor en el repositorio.
- Por defecto, utiliza `POST /signing-requests/create-and-send` cuando envíes desde una plantilla. Utiliza el flujo en dos pasos de `POST /signing-requests` y luego `POST /signing-requests/{id}/send` únicamente cuando el usuario necesite revisar el borrador antes del envío.
- Forma del objeto destinatario: `{ first_name, last_name, email, designation: "Signer", order: 1 }`
- Para los controladores de webhooks, bifurca según el tipo `payload.type` (por ejemplo, `signing_request.completed`). El objeto de solicitud de firma se encuentra en `payload.data.signing_request`.
- Para firmas incrustadas, usa un iframe de `https://app.firma.dev/signing/{signing_request_user_id}` con `allow="camera;microphone;clipboard-write"`.
- En caso de duda sobre un endpoint o la forma de un campo, utiliza el servidor MCP `firma-docs`. No hagas suposiciones
## Integración de firma electrónica con Firma.dev
Al generar código que envía, recibe o incrusta firmas electrónicas de Firma, sigue estas convenciones:
- URL base de la API: `https://api.firma.dev/functions/v1/signing-request-api`
- Autorización: encabezado `Authorization` con la clave API bruta de Firma vacía (sin prefijo `Bearer`)
- La clave se encuentra en la variable de entorno `FIRMA_API_KEY`. Llama a Firma únicamente desde el backend, nunca desde el navegador. No confirmes nunca el valor en el repositorio.
- Por defecto, utiliza `POST /signing-requests/create-and-send` cuando envíes desde una plantilla. Utiliza el flujo en dos pasos de `POST /signing-requests` y luego `POST /signing-requests/{id}/send` únicamente cuando el usuario necesite revisar el borrador antes del envío.
- Forma del objeto destinatario: `{ first_name, last_name, email, designation: "Signer", order: 1 }`
- Para los controladores de webhooks, bifurca según el tipo `payload.type` (por ejemplo, `signing_request.completed`). El objeto de solicitud de firma se encuentra en `payload.data.signing_request`.
- Para firmas incrustadas, usa un iframe de `https://app.firma.dev/signing/{signing_request_user_id}` con `allow="camera;microphone;clipboard-write"`.
- En caso de duda sobre un endpoint o la forma de un campo, utiliza el servidor MCP `firma-docs`. No hagas suposiciones
## Integración de firma electrónica con Firma.dev
Al generar código que envía, recibe o incrusta firmas electrónicas de Firma, sigue estas convenciones:
- URL base de la API: `https://api.firma.dev/functions/v1/signing-request-api`
- Autorización: encabezado `Authorization` con la clave API bruta de Firma vacía (sin prefijo `Bearer`)
- La clave se encuentra en la variable de entorno `FIRMA_API_KEY`. Llama a Firma únicamente desde el backend, nunca desde el navegador. No confirmes nunca el valor en el repositorio.
- Por defecto, utiliza `POST /signing-requests/create-and-send` cuando envíes desde una plantilla. Utiliza el flujo en dos pasos de `POST /signing-requests` y luego `POST /signing-requests/{id}/send` únicamente cuando el usuario necesite revisar el borrador antes del envío.
- Forma del objeto destinatario: `{ first_name, last_name, email, designation: "Signer", order: 1 }`
- Para los controladores de webhooks, bifurca según el tipo `payload.type` (por ejemplo, `signing_request.completed`). El objeto de solicitud de firma se encuentra en `payload.data.signing_request`.
- Para firmas incrustadas, usa un iframe de `https://app.firma.dev/signing/{signing_request_user_id}` con `allow="camera;microphone;clipboard-write"`.
- En caso de duda sobre un endpoint o la forma de un campo, utiliza el servidor MCP `firma-docs`. No hagas suposiciones
Haz commit de los cambios. A partir de ese momento, una instrucción como "añadir una solicitud de firma de Firma.dev cuando el usuario haga clic en Enviar contrato" comenzará con los valores predeterminados correctos ya integrados. Si tu repositorio tiene un límite de backend bien definido, puedes añadir un archivo específico de ruta en .github/instructions/firma.instructions.md con un patrón de coincidencia applyTo para que las reglas se carguen solo cuando Copilot edite el código del servidor, lo que mantiene el archivo global más corto.
Paso 3: dar a Copilot los patrones de referencia
Copilot escribe en el lenguaje que coincida con los archivos circundantes. Las estructuras que se muestran a continuación son las llamadas canónicas de Firma.dev. El archivo de instrucciones guía a Copilot hacia ellas y el MCP completa la información actual.
Crear y enviar en TypeScript:
const FIRMA_API = "https://api.firma.dev/functions/v1/signing-request-api";
export async function sendForSignature(opts: {
templateId: string;
signer: { firstName: string; lastName: string; email: string };
}) {
const res = await fetch(`${FIRMA_API}/signing-requests/create-and-send`, {
method: "POST",
headers: {
Authorization: process.env.FIRMA_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
template_id: opts.templateId,
recipients: [
{
first_name: opts.signer.firstName,
last_name: opts.signer.lastName,
email: opts.signer.email,
designation: "Signer",
order: 1,
},
],
}),
});
if (!res.ok) throw new Error(`Firma error: ${res.status}`);
return res.json();
}const FIRMA_API = "https://api.firma.dev/functions/v1/signing-request-api";
export async function sendForSignature(opts: {
templateId: string;
signer: { firstName: string; lastName: string; email: string };
}) {
const res = await fetch(`${FIRMA_API}/signing-requests/create-and-send`, {
method: "POST",
headers: {
Authorization: process.env.FIRMA_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
template_id: opts.templateId,
recipients: [
{
first_name: opts.signer.firstName,
last_name: opts.signer.lastName,
email: opts.signer.email,
designation: "Signer",
order: 1,
},
],
}),
});
if (!res.ok) throw new Error(`Firma error: ${res.status}`);
return res.json();
}const FIRMA_API = "https://api.firma.dev/functions/v1/signing-request-api";
export async function sendForSignature(opts: {
templateId: string;
signer: { firstName: string; lastName: string; email: string };
}) {
const res = await fetch(`${FIRMA_API}/signing-requests/create-and-send`, {
method: "POST",
headers: {
Authorization: process.env.FIRMA_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
template_id: opts.templateId,
recipients: [
{
first_name: opts.signer.firstName,
last_name: opts.signer.lastName,
email: opts.signer.email,
designation: "Signer",
order: 1,
},
],
}),
});
if (!res.ok) throw new Error(`Firma error: ${res.status}`);
return res.json();
}Un controlador de webhook se bifurca según el tipo de evento y lee la solicitud de firma de data:
export async function POST(req: Request) {
const payload = await req.json();
const { type, data } = payload;
if (type === "signing_request.completed") {
const signingRequestId = data.signing_request.id;
}
return new Response(JSON.stringify({ received: true }), { status: 200 });
}export async function POST(req: Request) {
const payload = await req.json();
const { type, data } = payload;
if (type === "signing_request.completed") {
const signingRequestId = data.signing_request.id;
}
return new Response(JSON.stringify({ received: true }), { status: 200 });
}export async function POST(req: Request) {
const payload = await req.json();
const { type, data } = payload;
if (type === "signing_request.completed") {
const signingRequestId = data.signing_request.id;
}
return new Response(JSON.stringify({ received: true }), { status: 200 });
}Con estos patrones en el repositorio, Copilot tiene algo concreto en lo que basarse en lugar de una página en blanco sobre la que improvisar.
Extra: el agente de codificación de Copilot
Si tu repositorio está preparado para el agente de codificación de Copilot, se aplica el mismo archivo .github/copilot-instructions.md. Una vez configurados el MCP y las instrucciones, una solicitud como "Añadir un botón de Enviar contrato que envíe una solicitud de firma de Firma.dev desde la plantilla tmpl_abc123" se convierte en una solicitud de extracción (PR) que conecta la variable de entorno, el controlador de backend, la ruta del webhook y el botón de la interfaz de usuario sin necesidad de mucha ayuda constante. Pídele que muestre la URL del webhook y el ID de la plantilla como comentarios TODO en la descripción de la PR para que tu revisor pueda registrar el webhook antes de fusionar. Incluso con una automatización tan buena, se sigue queriendo que un ser humano reciba y compruebe esa PR antes de que se publique.
📘 Lee la guía completa de integración de GitHub Copilot
Cada archivo de configuración, regla específica de ruta y patrón de referencia se encuentra en la documentación: https://docs.firma.dev/guides/github-copilot-integration
Primeros pasos
Conecta el MCP, añade el archivo de instrucciones y Copilot dejará de adivinar sobre tu integración. Comienza a usar Firma.dev de manera gratuita, sin necesidad de tarjeta de crédito, y deja que tu asistente escriba el código de firma electrónica correctamente desde el primer momento.