Zum Hauptinhalt springen

MCP-Server

@formfeed/mcp stellt Formfeed Agenten bereit, die das Model Context Protocol (MCP) sprechen: Claude Desktop, Claude Code, Cursor, VS Code, Zapier-Agenten und Ihre eigenen. Er läuft auf eine von zwei Arten:

  • Lokal (stdio): Ihr Client startet npx -y @formfeed/mcp mit einem API-Schlüssel in FORMFEED_API_KEY. Siehe Lokal betreiben.
  • Gehostet (Streamable HTTP): Ihr Client verbindet sich mit https://mcp.formfeed.dev/mcp, mit einem API-Schlüssel oder per Anmeldung mit Ihrem Formfeed-Konto. Siehe Gehosteter Endpunkt.

Ein Server handelt in einem Workspace: dem, für den sein API-Schlüssel angelegt wurde, oder dem, den Sie bei der Anmeldung wählen. In der offiziellen MCP-Registry steht der Server als io.github.formfeed-dev/formfeed.

Tools​

ToolWas es tutKosten
list_templatesDie Vorlagen des Workspace, zuletzt geänderte zuerst und ohne archivierte: id (tpl_…), Slug, Name, Art (pdf, image, docx, pptx), Engine, Beschreibung, Tags und published_version (null heißt nie veröffentlicht, render kann sie also noch nicht nutzen). Filtert nach Art, Engine, Tag und Suchekostenlos
get_template_schemaDas JSON-Schema der data, die eine Vorlage erwartet, und ihre Beispieldaten, aus der veröffentlichten Version, sonst aus dem neuesten Entwurf. Speichert die Vorlage kein Schema, wird eines aus den Beispieldaten abgeleitet: ein Anhaltspunkt, kein Vertragkostenlos
validate_templatePrüft eine Vorlage mit Daten, ohne zu rendern; gespeichert wird nichts. Mit einem Slug prüft die API die veröffentlichte Version (sonst den neuesten Entwurf) wie ein Rendering: Syntax, Kopf- und Fußzeile, Fehler, die erst mit diesen Daten auftreten, und die Daten gegen das gespeicherte Datenschema (ein falscher Typ oder ein fehlendes Pflichtfeld ist ein Fehler). Mit html plus engine kompiliert es offline und meldet Syntaxfehler, unbekannte Filter und fehlende Variablen. Liefert ok und diagnostics; bei einer Word- oder PowerPoint-Vorlage nennt ein Befund Teil und Absatz. Warnungen lassen ok auf truekostenlos
check_invoicePrüft den _invoice-Block einer E-Rechnung offline, wie die API es vor dem Rendern tut: die Felder, die EN 16931 verlangt, die Summen auf den Cent, Umsatzsteuerkategorien und Codelisten sowie Frankreichs Regeln für eine Rechnung zwischen zwei französischen Unternehmen. An die API geht nichts. Liefert ok und problems, jedes mit dem Feld (path), der Regel (BR-…), wo eine greift, und einer Meldungkostenlos
renderRendert eine gespeicherte Vorlage oder rohes HTML mit Daten und liefert das Rendering mit status und download_url: PDF, PNG, JPG oder WebP sowie DOCX, PPTX oder PDF für Word- und PowerPoint-Vorlagen; ohne output entscheidet die Vorlage. Eine gespeicherte Vorlage rendert ihre veröffentlichte Version. Mit einvoice wird das PDF eine ZUGFeRD- / Factur-X-E-Rechnung aus data._invoice, und das Rendering trägt den Bericht des Validators. Ein Bild bis 2 MB kommt zusätzlich als Bild zurück, das der Agent ansehen kann; ein PDF kommt als LinkEinheiten; kostenlos mit Test-Schlüssel
convert_to_pdfWandelt ein vorhandenes Word-, Excel-, PowerPoint-, OpenDocument-, RTF- oder HTML-Dokument (bis 20 MB, wird nicht gespeichert) oder das Rendering einer Word- oder PowerPoint-Vorlage unverändert, ohne Daten, in ein PDF um und liefert das Rendering. Übergeben Sie render_id, file_base64 mit file_name oder, nur beim lokalen Server, pathEinheiten wie ein PDF dieser Länge; ab dem Starter-Tarif
get_renderStatus, download_url mit ihrem expires_at, Seitenzahl, Einheiten und Fehler eines Renderings. Es stellt einen frischen Link aus, ist also der Weg, wenn der alte abgelaufen istkostenlos
get_workspaceWorkspace (mit seiner Region) und Organisation, in denen der Server arbeitet, der Tarif, die Umgebung (live oder test) und die Einheiten des laufenden Zeitraums: enthaltene, verbrauchte und übrige vorausbezahltekostenlos

Ein typischer Ablauf für Agenten: list_templates → get_template_schema → Daten bauen → validate_template → render → download_url an den Nutzer geben.

Für eine E-Rechnung baut der Agent den _invoice-Block, korrigiert ihn mit check_invoice, bis er ok ist, und ruft render mit einvoice und dem Block als data._invoice auf. Die Vorlage druckt denselben Block, wie es das Beispiel „E-Rechnung“ der Galerie tut. Eine abgelehnte Rechnung kommt als Tool-Fehler zurück, der jedes Feld und jede Regel nennt, sodass der Agent den Block korrigieren und es erneut versuchen kann. Live-E-Rechnungen brauchen den Starter-Tarif; Test-Schlüssel erzeugen eine begrenzte Zahl am Tag, jede mit der Testmarkierung (siehe Tarife und Einheiten).

Jedes Tool antwortet neben dem Text mit strukturiertem Inhalt und gibt dessen Form als Ausgabeschema an (outputSchema in MCP), sodass ein Client die Felder prüfen kann, die er liest: status, download_url und units eines Renderings, die diagnostics einer Prüfung, Tarif und Einheiten des Workspace. Ein Tool-Fehler kommt nur als Text.

Argumente​

Der Agent liest sie vom Server selbst; hier stehen sie, damit Sie wissen, worauf er zugreifen kann. Jedes Argument ist optional, sofern nicht anders vermerkt, und ein Tool ohne Argumente braucht keine.

list_templates — schränkt die Liste ein; ohne Argumente kommen alle Vorlagen des Workspace zurück.

ArgumentTypBedeutung
kindpdf | image | docx | pptxNur Vorlagen dieser Art
enginejinja2 | liquid | handlebarsNur Vorlagen in dieser Engine
tagStringGenau dieser Tag, wie die App ihn schreibt (klein, mit Bindestrichen)
qStringSuche in Name und Slug, ohne Unterschied von Groß- und Kleinschreibung

get_template_schema

ArgumentTypBedeutung
templateString, erforderlichSlug oder tpl_…-ID. Die veröffentlichte Version, sonst die neueste

validate_template — entweder template oder html mit engine.

ArgumentTypBedeutung
templateStringSlug oder tpl_…-ID
htmlStringVorlagenquelle, wenn kein Slug angegeben ist
enginejinja2 | liquid | handlebarsMit html erforderlich
dataObjektWird gegen die Vorlage geprüft; ohne Angabe gelten die Beispieldaten der Vorlage

check_invoice

ArgumentTypBedeutung
invoiceObjekt, erforderlichDer _invoice-Block, mit den Feldern der Feldreferenz
profileen16931 | basicDas Profil, das das Rendering verlangen wird, ohne Angabe en16931. basic kann keinen Rundungsbetrag tragen und wird zwischen zwei französischen Unternehmen abgelehnt

render — entweder template oder html.

ArgumentTypBedeutung
templateStringSlug oder tpl_…-ID. Rendert die veröffentlichte Version; eine nie veröffentlichte Vorlage scheitert mit template_not_found
htmlStringEin vollständiges HTML-Dokument statt einer Vorlage, bis 5 MB
enginejinja2 | liquid | handlebarsFür html mit Vorlagensyntax, die aus data gefüllt wird
dataObjektWird an die Vorlage gebunden, in der Form, die get_template_schema beschreibt
outputpdf | png | jpg | webp | docx | pptxOhne Angabe entscheidet die Vorlage: PDF bei PDF-Vorlagen und html, das Bildformat bei Bildvorlagen, die Vorgabe bei Word- und PowerPoint-Vorlagen. Word-Vorlagen rendern docx oder pdf, PowerPoint-Vorlagen pptx oder pdf
filenameStringName der Datei hinter download_url, etwa rechnung-2026-0042.pdf
localeStringBCP-47-Tag für Helfer und Übersetzungen, etwa de-DE
waitBoolean, Vorgabe trueDas Tool fragt das Dokument synchron an, die meisten Renderings sind also fertig, wenn es antwortet. Ein Rendering, das länger als die synchrone Grenze der API (eine Minute) braucht, läuft im Hintergrund weiter: mit true wartet das Tool darauf, bis zu zwei weitere Minuten; mit false liefert es das Rendering im aktuellen Stand (queued oder rendering), das Sie mit get_render verfolgen
einvoiceBoolean | ObjektMacht das PDF zu einer E-Rechnung aus data._invoice: true für die Vorgaben oder die Optionen profile, flavour, xml und display_check; false schaltet ab, was die Vorlage erklärt. Nur PDF. Live-E-Rechnungen ab dem Starter-Tarif; Test-Renderings erzeugen eine begrenzte Zahl am Tag, jede mit der Testmarkierung

convert_to_pdf — genau eine Quelle angeben: render_id, file_base64 (mit file_name) oder path.

ArgumentTypBedeutung
render_idStringrnd_… eines Renderings mit Ausgabe docx oder pptx
file_base64StringDas Dokument selbst, base64-kodiert, bis 20 MB
file_nameStringMit file_base64 erforderlich. Sein Name, etwa report.xlsx; der Typ wird aus dem Inhalt gelesen, nicht aus der Endung
pathStringAbsoluter Pfad einer Datei auf diesem Rechner. Nur lokaler Server: Der gehostete Endpunkt bietet dieses Argument nicht an und hat keinen Zugriff auf Ihre Festplatte
page_rangesStringZu konvertierende Seiten, etwa 1-3,5; ohne Angabe alle Seiten
landscapeBooleanQuerformat, für Tabellen und Dokumente ohne eigenes Seiten-Setup
single_page_sheetsBooleanJedes Tabellenblatt auf eine Seite
filenameStringName des PDFs; ohne Angabe der Name des Dokuments mit .pdf

get_render

ArgumentTypBedeutung
idString, erforderlichrnd_…-ID des Renderings

get_workspace nimmt keine Argumente. Es antwortet mit workspace, organization, plan, environment, period und units, wie GET /account.

Lokal betreiben (stdio)​

Der lokale Server braucht Node.js 22 oder neuer; npx lädt und startet ihn. Claude Desktop (claude_desktop_config.json) und Cursor (~/.cursor/mcp.json für alle Projekte, .cursor/mcp.json für eines) nehmen denselben Eintrag:

{
"mcpServers": {
"formfeed": {
"command": "npx",
"args": ["-y", "@formfeed/mcp"],
"env": { "FORMFEED_API_KEY": "ff_test_…" }
}
}
}

Claude Code fügt ihn mit einem Befehl hinzu. Der Name des Servers steht vor --env, denn die Option nimmt mehrere Werte und hielte den Namen sonst für einen davon; alles nach -- ist der Befehl, den Claude Code startet:

claude mcp add --transport stdio formfeed --env FORMFEED_API_KEY=ff_test_… -- npx -y @formfeed/mcp

VS Code liest .vscode/mcp.json; der Schlüssel heißt dort servers, und eine Eingabevariable hält den API-Schlüssel aus der Datei heraus:

{
"inputs": [
{
"type": "promptString",
"id": "formfeed-key",
"description": "Formfeed API key",
"password": true
}
],
"servers": {
"formfeed": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@formfeed/mcp"],
"env": { "FORMFEED_API_KEY": "${input:formfeed-key}" }
}
}
}

Der lokale Server liest diese Umgebungsvariablen:

VariableBedeutung
FORMFEED_API_KEYEin API-Schlüssel des Workspace. Ohne ihn startet der Server nur mit den Offline-Prüfungen, validate_template mit html und check_invoice; jedes andere Tool antwortet, wie man einen Schlüssel bekommt
FORMFEED_REGIONeu (die Vorgabe) oder us: der API-Host dieser Region. Jeder Workspace liegt heute in der EU
FORMFEED_BASE_URLEine andere API-Adresse, mit /v1, etwa https://api-eu.formfeed.dev/v1; sie geht der Region vor

Nutzen Sie beim Bauen einen Test-Schlüssel (ff_test_…): Seine Renderings sind kostenlos (im Free-Tarif mit Testmarkierung). Wechseln Sie auf einen Live-Schlüssel (ff_live_…), wenn der Agent in Produktion geht. Der Schlüssel braucht die Scopes der Tools, die der Agent nutzt; die Vorgaben eines neuen Schlüssels (render:create, render:read, template:read, account:read) decken alle acht ab.

Eine Schritt-für-Schritt-Einrichtung für 18 Clients und Agent-Frameworks (Claude Desktop und Code, Cursor, VS Code, Windsurf (heute Devin Desktop), Zed, Codex, Gemini CLI, das OpenAI Agents SDK, LangChain, Mastra und weitere) finden Sie unter formfeed.dev/agents.

Für Coding-Agenten fügt das Formfeed-Plugin den gehosteten Server zusammen mit zwei Skills hinzu, die Vorlagen und den Code, der sie rendert, schreiben und prüfen: siehe Coding-Agenten.

Gehosteter Endpunkt​

mcp.formfeed.dev liefert dieselben Tools über Streamable HTTP, für Clients, die sich aus der Ferne verbinden (Claude.ai-Konnektoren, Claude Code, Cursor, ChatGPT, n8n und die Agenten-Frameworks):

URLAnmeldung mitFür
https://mcp.formfeed.dev/mcpIhrem Formfeed-Konto (OAuth) oder Authorization: Bearer ff_…alle: Ein Chat-Client öffnet die Anmeldung selbst, und Sie wählen den Workspace; ein Server oder eine Automatisierung schickt den API-Schlüssel
https://mcp.formfeed.dev/mcp/<workspace id>Ihrem Formfeed-Konto (OAuth)eine zweite Verbindung, die in einem anderen Workspace arbeiten soll als dem gewählten

Mit einem API-Schlüssel schickt der Client ihn als Header. In Claude Code:

claude mcp add --transport http formfeed https://mcp.formfeed.dev/mcp --header "Authorization: Bearer ff_test_…"

Ein Client, der Server nachschlägt, bevor er sich verbindet, findet diesen über https://formfeed.dev/.well-known/ai-catalog.json, das auf die Server Card des Endpunkts zeigt, https://mcp.formfeed.dev/mcp/server-card: Name, Version und beide Adressen, ohne Schlüssel lesbar.

Anmeldung mit Ihrem Konto​

Tragen Sie https://mcp.formfeed.dev/mcp ohne Schlüssel im Client ein. Er entdeckt den OAuth-Server von Formfeed, registriert sich selbst und öffnet den Browser: Sie melden sich bei Formfeed an, falls noch nicht geschehen, sehen, welcher Client fragt und was er darf, wählen den Workspace, in dem der Agent arbeitet, und erlauben es. Der Client behält ein Token und erneuert es selbst; die Abmeldung im Client beendet den Zugriff.

# Claude Code
claude mcp add --transport http formfeed https://mcp.formfeed.dev/mcp

Der Workspace bleibt beim Client: Der Agent arbeitet dort, bis Sie es in der App unter Verbundene Agenten im Kontomenü ändern, wo jeder erlaubte Agent mit seinem Workspace steht und sich der Zugriff widerrufen lässt. Eine Änderung erreicht den Agenten innerhalb einer Stunde, mit seinem nächsten Token. Um in zwei Workspaces zugleich zu arbeiten, verbinden Sie den Client ein zweites Mal mit der eigenen Adresse des Workspace, https://mcp.formfeed.dev/mcp/<workspace id> (die ID steht unter Einstellungen → Details als Workspace-ID); ein so verbundener Client arbeitet dort, was auch immer für ihn gewählt ist.

Ein angemeldeter Agent handelt in diesem Workspace als Sie, aber mit höchstens vier Scopes, template:read, render:read, render:create und account:read, und nie mit mehr, als Ihre Rolle erlaubt (der Agent eines Betrachters kann nicht rendern). Er liest also Vorlagen und ihre Datenschemas, prüft Daten, rendert Dokumente und wandelt Office-Dateien um (Einheiten zählen wie bei jedem Rendering), liest die Renderings des Workspace und liest, in welchem Workspace er arbeitet und was der Zeitraum noch hat (get_workspace). Er kann keine Vorlagen veröffentlichen oder ändern, keine Dateien hochladen oder löschen und weder Webhooks, Schlüssel, Mitglieder noch Abrechnung verwalten, unabhängig von Ihrer Rolle. Ein angemeldeter Agent rendert immer live; zum kostenlosen Rendern beim Bauen verbinden Sie ihn stattdessen mit einem Test-Schlüssel.

Auf dem Endpunkt wird nichts gespeichert: Jede Anfrage bringt ihr Token mit, und die API prüft bei jedem Aufruf, dass Sie noch Mitglied des Workspace des Agenten sind.

Mit Zwei-Faktor-Authentifizierung auf Ihrem Konto arbeitet ein Agent erst, nachdem Sie ihn auf der Zustimmungsseite aus einer Sitzung erlaubt haben, die Ihren Code bestanden hat. Ein Agent, den Sie vor dem Einschalten der Zwei-Faktor-Authentifizierung erlaubt haben, wird ab seinem nächsten Token (innerhalb der Stunde) abgewiesen: Verbinden Sie ihn neu und erlauben Sie ihn noch einmal. Bis dahin, und für jeden Agenten, der nie so erlaubt wurde, antwortet die API mit 403 forbidden und dem Grund.

Den Endpunkt selbst betreiben​

Derselbe Server läuft überall, wo Node.js 22 läuft:

npx -y @formfeed/mcp --http --port 8790 --host 0.0.0.0

--port ist ohne Angabe 8790, --host ist 127.0.0.1. Der Server nimmt API-Schlüssel auf /mcp, mit jeder Anfrage als Authorization: Bearer ff_… gesendet, und ruft den API-Host auf, den FORMFEED_REGION oder FORMFEED_BASE_URL wählt. --auth-server <issuer> (oder FORMFEED_AUTH_SERVER) ergänzt die OAuth-Anmeldung auf /mcp und /mcp/<workspace id>; so läuft der gehostete Endpunkt. Der Server reicht die Zugriffstokens an die Formfeed-API weiter, und die nimmt nur Tokens der Formfeed-eigenen Anmeldung an: Ein selbst betriebener Endpunkt ist also für API-Schlüssel da. --public-origin <url> (oder FORMFEED_PUBLIC_ORIGIN) nennt den Origin, den Clients hinter einem Proxy sehen. Seine Server Card liegt unter /mcp/server-card dieses Origins.

Hinweise​

  • Die Validierung nutzt dieselbe Engine wie der Editor und die Render-Server, ein Agent kann Daten- oder Vorlagenprobleme also beheben, bevor Einheiten verbraucht werden.
  • Jeder Aufruf von render ist ein neues Rendering, das seine Einheiten zählt; zwischen Aufrufen wird nichts dedupliziert.
  • Fehler kommen als Tool-Fehler zurück, deren Text mit dem API-Problemcode beginnt (quota_exceeded: …, template_not_found: …), nie als Ausnahmen. Eine abgelehnte E-Rechnung (einvoice_data_invalid, einvoice_display_mismatch, pdfa_conversion_failed) bringt zusätzlich errors und den einvoice-Bericht des Problems mit, ein strikt gescheitertes PDF/UA (pdfua_validation_failed) sein accessibility-Urteil. Fehler listet jeden Code.