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.
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:
- Den Leitfaden lesen (
opticscript://skills) — die vollständige API, die Speicherregeln, die häufigsten Fallstricke. - Direktiven deklarieren —
//!INPUT:,//!OUTPUT:,//!PARAM:. validate_script— der Syntaxcheck braucht keine Eingabebilder und kostet nichts.- Erst dann
run_scriptmit 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:
analyze_imageauf die Datei — wie groß, wie hell, hat sie Transparenz?get_api_referencemitquery: "resize"— wie heißt die Methode wirklich?validate_scriptauf den Entwurf — Syntax in Ordnung?run_scriptmit Eingabe- und Ausgabepfad.compare_imageszwischen 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
- Team-Server — ein Server für das ganze Team, Bilder per ID über einen Artefakt-Speicher.
- Erste Schritte — Installation und die JS-Engine-Tour.
- API-Referenz — jede
Engine.*-Methode. - Beispiele — 70+ funktionierende Skripte.
- Kommandozeilen-Werkzeuge — dieselben Messungen ohne Agent.
