GitHub Copilot ist gut darin, Code zu schreiben, der richtig aussieht. Bei Integrationscode wird das jedoch zum Problem. Bittet man es, eine API für elektronische Signaturen anzubinden, erfindet es selbstbewusst einen Endpunkt, rät die Struktur eines Payloads oder greift zu einem Bearer-Präfix, das Ihr Anbieter gar nicht verwendet. Am Ende debuggen Sie den Assistenten, anstatt das Feature auszuliefern.
Die Lösung besteht darin, Copilot während der Arbeit den echten API-Vertrag zur Verfügung zu stellen. Firma.dev liefert einen Docs-MCP-Server und eine Reihe von Repo-Konventionen, die zusammen dazu bewinden, dass Copilot gleich im ersten Durchlauf korrekten Integrationscode generiert. Da Firma.dev eine API-first-Plattform für elektronische Signaturen ist, die mit 0,049 € pro Umschlag (~5¢ USD) ohne Mindestbeträge oder Nutzerlizenzen abgerechnet wird, ist die Integration an sich minimal. Es geht darum, Copilot diese kleine Integration korrekt und nicht nur plausibel schreiben zu lassen.
Dies umfasst drei Einrichtungsschritte: Verbinden des Docs-MCP, Hinzufügen einer repositoriumsweiten Anweisungsdatei und Bereitstellen der Referenzmuster für Copilot.
Schritt 1: Verbindung zum Firma.dev Docs-MCP herstellen
Der Docs-MCP-Server stellt die vollständige Dokumentation von Firma.dev als durchsuchbare Tools bereit. Sobald er verbunden ist, fragt Copilot echte Endpunkte, aktuelle Request-Formate und Webhook-Payload-Schemas ab, anstatt zu raten. Er ist schreibgeschützt und erfordert keine Authentifizierung, sodass Sie niemals einen API-Schlüssel an ihn übergeben.
Fügen Sie ihn in VS Code auf Workspace-Ebene in .vscode/mcp.json hinzu:
{
"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"
}
}
}Laden Sie das Fenster neu und vergewissern Sie sich, dass firma-docs in der Tool-Auswahl von Copilot Chat angezeigt wird. Für die Copilot-CLI fügen Sie denselben Server zu ~/.copilot/mcp-config.json hinzu und starten Sie neu. Öffnen Sie in JetBrains oder Visual Studio Einstellungen → Copilot → MCP-Server und fügen Sie einen HTTP-Server namens firma-docs mit der URL https://docs.firma.dev/mcp hinzu.
Schritt 2: Eine repositoriumsweite Copilot-Anweisungsdatei hinzufügen
Die Datei .github/copilot-instructions.md wird von Copilot Chat, dem Coding-Agenten und bei Code-Reviews in jeder unterstützten Umgebung automatisch geladen. Hier legen Sie die Konventionen fest, die dafür sorgen, dass der generierte Code dem Vertrag entspricht. Erstellen Sie die Datei oder hängen Sie Folgendes an:
## Integration der elektronischen Signatur von Firma.dev
Befolgen Sie diese Konventionen, wenn Sie Code generieren, der elektronische Signaturen von Firma sendet, empfängt oder einbettet:
- API-Basis-URL: `https://api.firma.dev/functions/v1/signing-request-api`
- Auth: Header `Authorization` gesetzt auf den rohen Firma-API-Schlüssel (ohne `Bearer`-Präfix)
- Der Schlüssel befindet sich in `FIRMA_API_KEY` als Umgebungsvariable. Rufen Sie Firma nur vom Backend aus auf, niemals über den Browser. Checken Sie den Wert niemals ein.
- Standardmäßig `POST /signing-requests/create-and-send` verwenden, wenn aus einer Vorlage gesendet wird. Verwenden Sie den zweistufigen Ablauf `POST /signing-requests` und dann `POST /signing-requests/{id}/send` nur dann, wenn der Benutzer den Entwurf vor dem Senden überprüfen muss.
- Struktur des Empfänger-Objekts: `{ first_name, last_name, email, designation: "Signer", order: 1 }`
- Für Webhook-Handler verzweigen Sie nach `payload.type` (z. B. `signing_request.completed`). Das Signaturanforderungs-Objekt befindet sich unter `payload.data.signing_request`.
- Für eingebettetes Signieren nutzen Sie ein iframe auf `https://app.firma.dev/signing/{signing_request_user_id}` mit `allow="camera;microphone;clipboard-write"`.
- Wenn Sie sich bezüglich eines Endpunkts oder einer Feldstruktur unsicher sind, verwenden Sie den MCP-Server `firma-docs`. Raten Sie nicht
## Integration der elektronischen Signatur von Firma.dev
Befolgen Sie diese Konventionen, wenn Sie Code generieren, der elektronische Signaturen von Firma sendet, empfängt oder einbettet:
- API-Basis-URL: `https://api.firma.dev/functions/v1/signing-request-api`
- Auth: Header `Authorization` gesetzt auf den rohen Firma-API-Schlüssel (ohne `Bearer`-Präfix)
- Der Schlüssel befindet sich in `FIRMA_API_KEY` als Umgebungsvariable. Rufen Sie Firma nur vom Backend aus auf, niemals über den Browser. Checken Sie den Wert niemals ein.
- Standardmäßig `POST /signing-requests/create-and-send` verwenden, wenn aus einer Vorlage gesendet wird. Verwenden Sie den zweistufigen Ablauf `POST /signing-requests` und dann `POST /signing-requests/{id}/send` nur dann, wenn der Benutzer den Entwurf vor dem Senden überprüfen muss.
- Struktur des Empfänger-Objekts: `{ first_name, last_name, email, designation: "Signer", order: 1 }`
- Für Webhook-Handler verzweigen Sie nach `payload.type` (z. B. `signing_request.completed`). Das Signaturanforderungs-Objekt befindet sich unter `payload.data.signing_request`.
- Für eingebettetes Signieren nutzen Sie ein iframe auf `https://app.firma.dev/signing/{signing_request_user_id}` mit `allow="camera;microphone;clipboard-write"`.
- Wenn Sie sich bezüglich eines Endpunkts oder einer Feldstruktur unsicher sind, verwenden Sie den MCP-Server `firma-docs`. Raten Sie nicht
## Integration der elektronischen Signatur von Firma.dev
Befolgen Sie diese Konventionen, wenn Sie Code generieren, der elektronische Signaturen von Firma sendet, empfängt oder einbettet:
- API-Basis-URL: `https://api.firma.dev/functions/v1/signing-request-api`
- Auth: Header `Authorization` gesetzt auf den rohen Firma-API-Schlüssel (ohne `Bearer`-Präfix)
- Der Schlüssel befindet sich in `FIRMA_API_KEY` als Umgebungsvariable. Rufen Sie Firma nur vom Backend aus auf, niemals über den Browser. Checken Sie den Wert niemals ein.
- Standardmäßig `POST /signing-requests/create-and-send` verwenden, wenn aus einer Vorlage gesendet wird. Verwenden Sie den zweistufigen Ablauf `POST /signing-requests` und dann `POST /signing-requests/{id}/send` nur dann, wenn der Benutzer den Entwurf vor dem Senden überprüfen muss.
- Struktur des Empfänger-Objekts: `{ first_name, last_name, email, designation: "Signer", order: 1 }`
- Für Webhook-Handler verzweigen Sie nach `payload.type` (z. B. `signing_request.completed`). Das Signaturanforderungs-Objekt befindet sich unter `payload.data.signing_request`.
- Für eingebettetes Signieren nutzen Sie ein iframe auf `https://app.firma.dev/signing/{signing_request_user_id}` mit `allow="camera;microphone;clipboard-write"`.
- Wenn Sie sich bezüglich eines Endpunkts oder einer Feldstruktur unsicher sind, verwenden Sie den MCP-Server `firma-docs`. Raten Sie nicht
Checken Sie die Datei ein. Ab diesem Zeitpunkt startet ein Prompt wie „Füge eine Firma.dev-Signaturanforderung hinzu, wenn der Benutzer auf Vertrag senden klickt“ direkt mit den richtigen Standardeinstellungen. Wenn Ihr Repository eine klare Backend-Grenze hat, können Sie eine pfadspezifische Datei unter .github/instructions/firma.instructions.md mit einem applyTo-Glob anlegen, sodass die Regeln nur geladen werden, wenn Copilot Ihren Server-Code bearbeitet. Das hält die globale Datei kurz.
Schritt 3: Copilot die Referenzmuster zur Verfügung stellen
Copilot schreibt in der Sprache, die zu den umliegenden Dateien passt. Die folgenden Strukturen sind die kanonischen Aufrufe für Firma.dev. Die Anweisungsdatei lenkt Copilot in diese Richtung, und der MCP steuert die aktuellen Details bei.
Erstellen und Senden in 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();
}Ein Webhook-Handler verzweigt je nach Ereignistyp und liest die Signaturanforderung aus data aus:
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 });
}Mit diesen Mustern im Repository hat Copilot einen konkreten Anhaltspunkt, anstatt auf einer leeren Seite improvisieren zu müssen.
Bonus: Der Copilot-Coding-Agent
Wenn Ihr Repository für den Copilot-Coding-Agenten eingerichtet ist, gilt dieselbe Datei .github/copilot-instructions.md. Sobald der MCP und die Anweisungen vorhanden sind, wird ein Issue wie „Füge einen 'Vertrag senden'-Button hinzu, der eine Firma.dev-Signaturanforderung aus der Vorlage tmpl_abc123 sendet“ zu einem PR, der die Umgebungsvariable, den Backend-Handler, die Webhook-Route und den UI-Button ohne viel Zutun miteinander verknüpft. Bitten Sie ihn, die Webhook-URL und die Vorlagen-ID als TODOs in der PR-Beschreibung aufzuführen, damit Ihr Reviewer den Webhook vor dem Mergen registrieren kann. Selbst bei einer so guten Automatisierung sollten Sie vor der Veröffentlichung immer noch einen Menschen diesen PR prüfen lassen.
📘 Lesen Sie den vollständigen Leitfaden zur GitHub-Copilot-Integration
Jede Konfigurationsdatei, pfadspezifische Regel und jedes Referenzmuster finden Sie in der Dokumentation: https://docs.firma.dev/guides/github-copilot-integration
Erste Schritte
Verbinden Sie den MCP, fügen Sie die Anweisungsdatei hinzu, und Copilot hört auf, bei Ihrer Integration zu raten. Starten Sie kostenlos mit Firma.dev, keine Kreditkarte erforderlich, und lassen Sie Ihren Assistenten den Code für elektronische Signaturen auf Anhieb richtig schreiben.