· Martin Swoboda

Derselbe KI-Build ging von 30 Minuten auf 4 — das haben wir an unserem MCP-Server geändert

Bilder hochzuladen war der langsamste und fragilste Teil beim Bauen einer Website mit einem KI-Agenten. Wir haben es auf Protokollebene gelöst. Hier steht, was sich an Neletos MCP-Server geändert hat — mit den Vorher-Nachher-Zahlen.
Derselbe KI-Build ging von 30 Minuten auf 4 — das haben wir an unserem MCP-Server geändert

Wir bauen viele Websites per Prompt. Genau dafür liefern wir ein CMS mit einem nativen MCP-Server aus: Du zeigst Claude eine fertige HTML-Seite, und sie kommt als komponentenbasierte Website zurück, in der jede Überschrift, jeder Link und jedes Bild bearbeitbar ist.

Also haben wir getan, was man mit dem eigenen Produkt immer tun sollte — wir haben uns hingesetzt und die Zeit gestoppt.

Unser ursprüngliches Build-Rezept brauchte rund 30 Minuten für eine einzige Landingpage. Wir haben es neu geschrieben, die redundanten Schritte gestrichen und sind auf 14 Minuten gekommen. Guter Fortschritt. Aber dann haben wir uns angeschaut, wohin diese 14 Minuten eigentlich gingen, und die Antwort war unangenehm.

Die Website selbst — fünfzehn Komponenten, ein Layout, eine Seite, alles verdrahtet — brauchte 3 Minuten 40 Sekunden. Die restlichen zehn Minuten waren fünf Bilder. Vierzehn Kilobyte davon.

Fünf kleine Bilder kosteten fast dreimal so viel wie der gesamte Rest der Seite. Das ist kein langsamer Schritt, den man optimiert. Das ist ein Konstruktionsfehler, und kein noch so gutes Prompt-Tuning würde ihn beheben — er musste im Server behoben werden.

Warum Bilder langsam waren (es ist nicht, was du denkst)

Die naheliegende Theorie ist Netzwerk oder Speicher. Es war beides nicht — es war die KI.

Wenn ein Agent eine Datei über einen Tool-Aufruf hochlädt, reisen die Bytes als base64-Text — und dieser Text muss vom Modell erzeugt werden, Token für Token. Aus einem 5-KB-Bild werden ungefähr 7.000 Zeichen, die das Modell einzeln ausschreiben muss, Stück für Stück. Das CMS war nicht langsam. Der Upload war langsam, weil ein Sprachmodell mühsam ein Bild buchstabierte.

Es war außerdem auf eine Art fragil, die wirklich schwer zu debuggen ist. Eine unserer Testdateien scheiterte zweimal mit einem Padding-Fehler. Die Ursache war am Ende eine lange Folge wiederholter Zeichen im base64, die irgendwo auf dem Weg zusammengefaltet wurde — der Server empfing 1.621 Zeichen, wo 1.624 gesendet wurden. Es scheitert nicht laut auf der Transportebene; es taucht viel später als Datei-defekt-Fehler auf, der dich auf ein völlig falsches Problem zeigt.

Das zweite Problem war leiser, aber in der Summe größer: unsere API war zu geschwätzig. Jede Schreiboperation gab den vollständigen gespeicherten Datensatz zurück. Speicher eine Seite mit elf Elementen, und du bekamst die komplette Komponentendefinition jedes Elements zurück — Template, CSS, JavaScript, Formular-Schema — einmal pro Element wiederholt. Das sind etwa 55 KB JSON, die genau den Inhalt zurückwerfen, den der Aufrufer gerade gesendet hatte. Rechne das über einen ganzen Build hoch, und der Großteil der Token-Kosten waren keine Anweisungen. Es waren wir, die mit uns selbst redeten.

Was wir ausgeliefert haben

Zwei Änderungen, beide auf Protokollebene.

1. Bilder können jetzt inline aufgenommen werden. Statt eine Datei hochzuladen und dann ihre ID in deinen Inhalt einzubauen, setzt du die URL direkt in die Elementdaten:

"data": {
  "image": { "sourceUrl": "https://example.com/studio.jpg" }
}

Der Server holt sie, speichert sie und setzt die echte Datei-ID ein — innerhalb desselben Speichervorgangs, in derselben Transaktion. Kein base64. Kein separater Upload-Schritt. Die Bytes laufen überhaupt nie durch das Modell.

2. Antworten können leise sein. Jedes Schreib-Tool nimmt jetzt ein optionales verbose: false:

{ "id": 53 }

Das ist jetzt die ganze Antwort, statt drei Kilobyte. Für Seiten und Layouts bekommst du weiterhin das Mapping der Element-IDs zurück — das Einzige, was der Aufrufer wirklich nicht selbst herausfinden kann — und sonst nichts. Der Standardwert ist true, es bricht also nichts für jemanden, der es schon aufruft.

Die Zahlen

Dieselbe Seite, dieselben Komponenten, dieselben fünf Bilder, drei Punkte auf dem Weg:

Ursprüngliches RezeptNeu geschriebenes RezeptNach den Server-Änderungen
Kompletter Build mit Bildern~30 Min~14 Min4 Min 0 s
Bild-Phase~10 Min10 Min 25 s0 s — in den Speichervorgang der Seite gefaltet
Tokens~225.000~40.000
Tool-Aufrufe21 + Uploads19

Es lohnt sich, diese beiden Sprünge ehrlich zu trennen, denn es sind unterschiedliche Arten von Arbeit.

Von 30 auf 14 Minuten zu kommen war Prompt-Engineering — weniger redundante Aufrufe, bessere Nutzung von Standardwerten, das Streichen von Schritten, die aus Aberglauben existierten. Nützlich, aber wir hatten es ungefähr so weit getrieben, wie es ging.

Von 14 auf 4 zu kommen war Protokollarbeit, und das ist das größere Ergebnis: grob 3,5× schneller und 6× günstiger bei identischem Build. Die Ersparnis kommt daher, dass wir eine Phase gelöscht haben, statt eine zu beschleunigen. Weil eine Seite jetzt mit ihren Elementen erstellt werden und Bild-URLs in einem Aufruf auflösen kann, wurde aus der Abfolge „leere Seite anlegen → fünf Dateien hochladen → alles zurückschreiben" ein einziger Speichervorgang.

Was die allgemeine Lehre für alle ist, die Agenten-Tooling bauen: Sobald du den Prompt aufgeräumt hast, stecken die verbleibenden Kosten fast immer in der Form der API, nicht in den Anweisungen des Agenten.

Warum das wichtig ist, wenn du auf Neleto baust

Deine Agent-Läufe kosten weniger. Der Token-Verbrauch bei einem Standard-Seiten-Build sank um rund 85%. Wenn du Builds wiederholt fährst — Kundenseiten, Templates, einen Kurs, eine Test-Suite —, ist das der Unterschied zwischen einem Experiment und etwas, das du routinemäßig machst.

Es gibt einen Weg weniger, deinen Inhalt kaputtzumachen. Unsere Elementdaten haben Replace-Semantik: Sendest du ein Teil-Update, werden die weggelassenen Werte gelöscht. Der alte Bild-Workflow erzwang einen zweiten Schreibdurchlauf über bereits gespeicherten Inhalt — genau die Situation, in der das zubeißt. Wir haben es beim Testen tatsächlich geschafft, den gesamten Text einer Seite so zu leeren — jeder Abschnitt renderte noch, nur leer. Mit Inline-Aufnahme gibt es keinen zweiten Durchlauf, also ist die Falle weg. (Es ist dieselbe Klasse stiller Fehler, gegen die wir Selbstprüfungen gebaut haben — den Fehlerfall gleich ganz zu löschen ist noch besser, als ihn zu fangen.)

Es lässt sich mit allem anderen kombinieren. sourceUrl akzeptiert jede URL, die der Server erreichen kann: die bestehende Medienbibliothek eines Kunden, ein CDN, ein generiertes Bild oder eine Datei, die schon in Neleto liegt. Für eine Agentur, die eine Website migriert, heißt das: Bilder können im selben Aufruf mitwandern, der die Seite erstellt.

Der ehrliche Teil

Ein paar Kanten, die du kennen solltest, bevor du an sie stößt.

Inline-Aufnahme braucht eine URL, die der Server erreichen kann. Wenn deine Bilder nur auf deinem Laptop existieren, musst du sie trotzdem erst irgendwo hosten — der base64-Weg existiert weiter für kleine Dateien, und bei ein paar KB ist er völlig in Ordnung. Bei großen Payloads fällt er auseinander.

Es gibt außerdem eine raue Kante, die wir beim Testen in unserer eigenen API gefunden haben: Die serveUrl einer Datei liefert eine 400, wenn du sie blank abrufst, ohne einen Skalierungs-Query-String anzuhängen. Das heißt, das Naheliegendste, was du versuchen würdest — aus einer Datei aufnehmen, die schon in deiner Neleto-Medienbibliothek liegt — scheitert, es sei denn, du hängst ?options=w_800,f_webp an. Wir beheben das. Bis dahin: häng die Optionen an.

Und eine Lehre, die überhaupt nicht von Bildern handelt. Die Inline-Aufnahme funktionierte in der Sekunde, in der sie deployte, weil Elementdaten frei geformt sind — keine Vertragsänderung. Das verbose-Flag brauchte eine Schema-Änderung, und Schemas werden einmal ausgehandelt, wenn ein Client sich verbindet, also blieb es für unseren eigenen Editor unsichtbar, bis wir uns neu verbanden. Wenn du MCP-Tooling baust: Änderungen auf Verhaltensebene erreichen Agenten sofort, solche auf Schema-Ebene brauchen eine Client-Runde. Plane deine Rollouts entsprechend.

Probier es aus

Beide Änderungen sind live. Wenn du schon mit dem Neleto-MCP-Server verbunden bist, funktioniert die Inline-Aufnahme genau jetzt — setz eine URL dahin, wo eine Datei-ID hingehört. Für verbose verbinde deinen Client neu, damit er das aktualisierte Schema aufnimmt.

Wenn du noch keine Website per Prompt gebaut hast, ist das ein guter Moment. Der langsamste, fragilste Teil des Workflows hat gerade aufgehört zu existieren.


Probier es selbst: Starte ein kostenloses Neleto-Projekt, zeig einem Agenten drauf und setz eine Bild-URL direkt in die Elementdaten — sieh zu, wie die ganze Upload-Phase verschwindet. Genau dafür ist ein nativer MCP-Server da, und wenn du den Deep Dive willst, wie er funktioniert, den haben wir geschrieben.

Schnelle Websites. Einfacher Content. KI-nativ.

Weiterlesen