MCP-Server

Bildbearbeitung als Werkzeug für KI-Agenten. OpticScript bringt einen Model-Context-Protocol-Server mit. Wer Claude, Gemini oder einen eigenen Agenten damit verbindet, gibt ihm nicht eine Handvoll fester Filter, sondern die ganze Skript-Engine: das Modell schreibt ein OpticScript-Skript und lässt es laufen.

Der Unterschied ist grundsätzlich. Ein MCP-Server mit den Werkzeugen resize, crop und blur kann drei Dinge. Dieser hier kann alles, was sich in OpticScript schreiben lässt — und das Modell kombiniert es selbst.


Was man fragen kann

Man fragt in normaler Sprache — der Agent wählt die Werkzeuge. Die Beispiele unten sind echte Läufe über den MCP-Server, mit einem Ordner aus fünf Urlaubsfotos; die Zahlen stammen aus diesen Läufen.

„Welche Fotos in meinem Urlaubsordner sind doppelt?“ Der Agent ruft image_hash für alle Dateien auf. Ergebnis: zwei Paare. IMG_4711.jpg und see_klein.jpg sind dasselbe Bild — die Kopie ist halb so groß und neu komprimiert, der Abstand trotzdem 0 Bit. cafe.webp und cafe (Kopie).webp ebenso. Die übrigen Fotos liegen 30–33 Bit auseinander, also verschiedene Bilder.

„Mach die Seefotos fürs Web fertig: WebP, lange Seite 1200 Pixel — und der Aufnahmeort soll nicht mit ins Netz.“ Ein run_script mit drei Zeilen (verkleinern, unsetMeta("exif.GPSInfo"), als WebP speichern), danach read_exif zur Kontrolle. Aus 1600×1067 und 393.718 Bytes werden 1200×800 und 108.220 Bytes, 73 % kleiner. Die GPS-Koordinaten sind weg, Copyright und Kameradaten bleiben. Wer den Ort nicht ausdrücklich erwähnt, behält ihn in der Datei — es lohnt sich, das dazuzusagen.

„Trag mich als Fotografin und das Copyright in die Café-Bilder ein.“ run_script mit mergeMeta("exif", { Artist, Copyright }), read_exif bestätigt: Fotografin „Anna Beispiel“, Copyright „© 2026 Anna Beispiel — alle Rechte vorbehalten“.

„Markiere das Seefoto mit meiner Kennung AB-2026.“ — und Wochen später: „Steckt in diesem Bild eine Kennung?“ run_script mit img.mark("AB-2026"), später img.readMark() auf einer Kopie, die eine Plattform quadratisch beschnitten, auf 640 Pixel verkleinert und neu komprimiert hat: gefunden, AB-2026. Beim Winterfoto: keine Kennung. Mehr dazu unter Copyright-Schutz — Markieren ist Pro, Prüfen frei.

„Welches Foto ist am schärfsten, und sind irgendwo Lichter ausgefressen?“ analyze_image für jedes Bild, kein Skript nötig. Das Seefoto ist mit Abstand am schärfsten (Schärfewert 0,027), das Winterbild liegt bei 0,005, das Café-Foto bei 0,0008 — weich gezeichnet, für einen großen Druck die schlechteste Wahl. Ausgefressene Lichter: bei keinem mehr als 0,04 % der Fläche.

Und eine Programmieraufgabe

„Mach mir einen Kontaktbogen aller Fotos aus dem Ordner, mit Dateiname und Aufnahmedatum unter jedem Bild.“

Dafür gibt es kein fertiges Werkzeug — der Agent schreibt das Skript selbst: schlägt drawText und blendAt mit get_api_reference nach, prüft den Entwurf mit validate_script und führt ihn mit fünf Eingängen aus. Die Dateinamen gibt er als Parameter mit, weil die Bilder über MCP als Daten ankommen, nicht als Dateien.

Kontaktbogen mit fünf Urlaubsfotos, darunter je Dateiname und Aufnahmedatum — vom Agenten geschrieben und über den MCP-Server ausgeführt

keys.forEach((key, i) => {
  const img = Engine.loadImage(key);
  const s = Math.max(TW / img.width, TH / img.height);       // Kachel füllen
  const cw = Math.round(TW / s), ch = Math.round(TH / s);
  img.crop(Math.round((img.width - cw) / 2), Math.round((img.height - ch) / 2), cw, ch).resize(TW, TH);
  sheet.blendAt(img, px(x, y), 1.0, Blend.Over);
  const raw = img.getMeta("exif")?.DateTimeOriginal;          // "2017:09:27 14:08:55"
  const date = raw ? raw.slice(0, 10).split(":").reverse().join(".") : "ohne Datum";
  sheet.drawText(names[i], x, y + TH + 24, { size: 18, color: "#e6edf3" });
  sheet.drawText(date,     x, y + TH + 46, { size: 15, color: "#8b98a9" });
});

Ausschnitt; das ganze Skript (30 Zeilen) liegt im Repository unter mlcprodweb/scripts/mcp_example_kontaktbogen.js. Seefoto: W. Bulach, CC BY-SA 4.0.


Die zehn Werkzeuge

Bilder verändern

Werkzeug Wofür
run_script Ein OpticScript-Skript ausführen. //!INPUT:-Schlüssel werden auf Bilddateien abgebildet, //!OUTPUT: landet auf der Platte. Ein Skript, das nur misst und über console.log antwortet, braucht gar keine Ausgabedatei.
validate_script Syntaxprüfung ohne Ausführung und ohne Eingabebilder. Meldet ok oder den Fehler mit Zeile und Spalte.

Bilder messen — seit 2.5.1, und der Grund dafür ist einfach: „ist das Foto scharf" ist keine Bildbearbeitung. Vorher musste ein Modell dafür ein Skript schreiben und ein Wegwerf-Ausgabebild erfinden.

Werkzeug Wofür
analyze_image Maße, Format, Helligkeit und Streuung je Kanal, Schärfe, abgesoffene Schatten und ausgefressene Lichter, Transparenz, Histogramm, dominante Farben, Wahrnehmungs-Hash, EXIF — in einem Aufruf.
compare_images MSE, PSNR, MAE, größte Einzelabweichung, Zahl der abweichenden Pixel, Hash-Abstand. Beantwortet „hat sich meine Ausgabe verändert" und „reicht diese JPEG-Qualität".
read_exif Kamera, Objektiv, Aufnahmezeit, Ausrichtung, Belichtung, Blende, ISO, Brennweite, GPS — sowie die Herkunftsangaben, die unsere eigenen Läufe einstempeln.
image_hash Wahrnehmungs-Hash mehrerer Dateien mit dem Bit-Abstand zur ersten. Findet Duplikate, übersteht Skalieren und Neukodieren.
image_info Nur Maße, Format und Dateigröße — ohne das Bild in die Engine zu laden.

Sich zurechtfinden

Werkzeug Wofür
get_api_reference Die JS-API-Referenz, auf Wunsch nach einem Stichwort gefiltert.
list_examples Die mitgelieferten Beispielskripte auflisten.
get_example Den Quelltext eines Beispiels holen.

Dazu eine Ressource (opticscript://skills) mit dem vollständigen Skript-Leitfaden und zwei Prompts: author_script schreibt ein Skript für eine beschriebene Aufgabe, fix_script arbeitet ein kaputtes gegen die echte API ab.


Warum die Reihenfolge zählt

Die Werkzeuge allein reichen einem Modell nicht. Ohne Anleitung schreibt es plausibel aussehendes JavaScript mit Methoden, die nach einer anderen Bildbibliothek klingen — und die Engine kennt sie nicht.

Deshalb steht die Reihenfolge im Prompt author_script:

  1. Den Leitfaden lesen (opticscript://skills) — die vollständige API, die Speicherregeln, die häufigsten Fallstricke.
  2. Direktiven deklarieren — //!INPUT:, //!OUTPUT:, //!PARAM:.
  3. validate_script — der Syntaxcheck braucht keine Eingabebilder und kostet nichts.
  4. Erst dann run_script mit den echten Pfaden.

Wer den Server einbindet, sollte diesen Prompt kennen. Er ist der Unterschied zwischen „das Modell rät" und „das Modell liefert".


Einbinden

Der Server läuft über stdio und wird als mlcos-mcp mitgeliefert.

Claude Desktop

Datei bearbeiten und Claude Desktop neu starten:

  • Windows — %APPDATA%\Claude\claude_desktop_config.json
  • macOS — ~/Library/Application Support/Claude/claude_desktop_config.json
  • Linux — ~/.config/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "mlc-opticscript": {
      "command": "C:\\Program Files\\MLC OpticScript\\mlcos-mcp.exe",
      "args": ["-root", "C:\\Users\\ich\\Bilder"]
    }
  }
}

Unter macOS zeigt der Pfad in das Programmpaket:

{
  "mcpServers": {
    "mlc-opticscript": {
      "command": "/Applications/MLC OpticScript.app/Contents/MacOS/mlcos-mcp",
      "args": ["-root", "/Users/ich/Bilder"]
    }
  }
}

Ein absoluter Pfad ist Pflicht: Claude Desktop startet den Server nicht in Ihrem Projektverzeichnis, und ein relativer Aufruf schlägt ohne sichtbare Meldung fehl.

Claude Code

claude mcp add mlc-opticscript -- /pfad/zu/mlcos-mcp -root ~/Bilder

Was -root bewirkt

Es gibt das Verzeichnis vor, aus dem Dokumentation und Beispielskripte gelesen werden, und ist zugleich der natürliche Arbeitsordner für Ein- und Ausgabedateien. Ohne die Angabe sucht der Server vom Arbeitsverzeichnis aufwärts — was auf dem Schreibtisch eines Clients selten dort landet, wo Ihre Bilder liegen.

Gebaut ist er auf dem offiziellen Go-SDK der MCP-Organisation und spricht die Protokollfassung 2026-07-28. Jede erzeugte Datei trägt Herkunftsangaben in den Metadaten — Engine-Version, Zeitstempel und via=mlcos-mcp —, sodass später nachvollziehbar bleibt, welcher Lauf sie erzeugt hat.


Ein Beispiel für den Ablauf

Ein Agent, der „mach mir aus dem Screenshot ein Thumbnail mit Rahmen" bekommt, geht typischerweise so vor:

  1. analyze_image auf die Datei — wie groß, wie hell, hat sie Transparenz?
  2. get_api_reference mit query: "resize" — wie heißt die Methode wirklich?
  3. validate_script auf den Entwurf — Syntax in Ordnung?
  4. run_script mit Eingabe- und Ausgabepfad.
  5. compare_images zwischen Eingabe und Ergebnis — ist überhaupt etwas passiert, und wie viel?

Fünf Aufrufe, und keiner davon rät. Schritt 5 ist der neue: ein Modell kann sein eigenes Ergebnis prüfen, statt es zu behaupten.


Siehe auch