🔬 Debugging inklusive

UploadFile & SetFileMetadata

Plan, Implementierung, Deprecation-Fix, DI-Cache-Diagnose – 447 Tests grün
📁 Projekt: typo3-mcp-server 📄 Log: new mcp tool upload 💬 3 Austausche ⏱ ~50 Minuten
Legende:
Vorbildlich
Problematisch
Achtung / Hinweis
Lerntipp

📋 Hintergrund

Die letzte große Feature-Session des FAL-Zweigs: Die KI soll nicht nur Dateien lesen und referenzieren, sondern auch selbst generierte Bilder hochladen und Metadaten setzen. Use-Case: KI generiert ein Bild, kodiert es als base64, lädt es in einen TYPO3-Storage, setzt Title/Alt-Text/Copyright in mehreren Sprachen.

Diese Session enthält drei Austausche – und damit mehr Interaktion als alle anderen Sessions. Der dritte Austausch entsteht durch einen echten Bug: Die KI kann das UploadFile-Tool nicht finden. Copilot diagnostiziert die Ursache eigenständig: TYPO3 DI-Container-Cache.

Architektur-Highlight: Copilot schlägt vor, eine neue abstrakte Basisklasse AbstractFileTool einzuführen und die bestehende GetFileMetadataTool zu refaktorieren – alles in einer Implementierungs-Session. Das ist kein kleines Feature, sondern ein Architektur-Upgrade.

💬 Session-Austausche

Austausch 1 — Plan: Upload & Metadaten
Entwickler
I need a new tool that allows to upload assets and metadata into TYPO3 storages and folders. make an implementation plan of this feature that follows TYPO3 coding guidelines and best practices and integrates seamlessly into the current extension architecture. Only use official TYPO3 APIs that respect user permissions, no direct access to the filesystem or database. the consuming AI shall be able to upload e.g. ai generated images and set and translate metadata
Konkreter Use-Case: "AI generated images". Dieser Zusatz ist wichtig – er impliziert base64-kodierte Bilddaten als Input (kein Dateisystem-Upload vom Browser). Copilot wählt daraufhin korrekt base64_decode → tempfile → $storage→addFile() als Implementierungsweg.
"Set and translate metadata" – lokalisiertes Schreiben gefordert. Der Prompt fordert explizit Übersetzungen. Copilot plant DataHandler-localize-Command für neue Übersetzungen – nicht nur Update bestehender.
Copilot
Ich sammle zunächst Kontext zur bestehenden Architektur, um den Plan fundiert erstellen zu können.

[liest GetFileMetadataTool, AbstractTool, WriteTableTool (für DataHandler-Pattern), McpServerFactory, AbstractFileTool-Kandidat, Test-Struktur]

Plan: UploadFile & SetFileMetadata MCP Tools

Zwei neue Tools im File/-Namespace, plus Architektur-Upgrade:

Steps:
1. UploadFileTool – Parameter: storageUid (int), folderPath (string), fileName (string), fileContent (string, base64), conflictMode (rename/replace/cancel). Nutzt $storage→addFile($tempFile, $folder, $fileName, $conflictMode). 10 MB Limit. Annotations: readOnlyHint=false, idempotentHint=false.
2. SetFileMetadataTool – Parameter: fileUid oder combinedIdentifier, language (ISO-Code), metadata-Objekt (title, description, alternative, copyright, creator, categories). Default-Sprache via DataHandler update, lokalisierte Sprachen via DataHandler localize-Command.
3. AbstractFileTool extrahieren – resolveFile() und resolveLanguageUid() aus GetFileMetadataTool in abstrakte Basisklasse auslagern. GetFileMetadataTool, UploadFileTool, SetFileMetadataTool erben davon. Pattern: AbstractRecordTool extends AbstractTool.
4. Functional Tests – UploadFileToolTest (11 Tests), SetFileMetadataToolTest (10 Tests). Bestehende CSV-Fixtures wiederverwenden.
5. Keine Services.yaml-Anpassung – AutoconfigureTag greift automatisch.

Further Considerations: Dateigröße/base64-Limit (10 MB Empfehlung), Kategorie-Zuweisung via MM-Relationen, AbstractFileTool vs. Trait (Empfehlung: AbstractFileTool, konsistent mit AbstractRecordTool).
Architektur-Upgrade im Plan. Copilot schlägt vor, AbstractFileTool einzuführen und GetFileMetadataTool zu refaktorieren – ohne dass der Prompt danach fragt. Das zeigt, dass Copilot DRY-Prinzipien aus dem Kontext ableitet.
conflictMode als Enum-Parameter. rename/replace/cancel – Copilot kennt die TYPO3 DuplicationBehavior-API und modelliert sie sauber als Enum-Parameter mit Default rename. Das ist API-Design, das dem TYPO3-Konzept entspricht.
DataHandler localize für neue Übersetzungen. Copilot unterscheidet zwischen Update (bestehende Übersetzung vorhanden) und localize (neue Übersetzung anlegen via DataHandler-Command). Das ist korrektes TYPO3-Verhalten.
Austausch 2 — Implementierung mit Deprecation-Fix
Entwickler
Start implementation
Minimaler Trigger. Wie in MCP3 reichen zwei Wörter. Der Plan-Kontext ist vollständig.
Copilot
Ich starte die Implementierung. Zunächst lese ich noch ein paar fehlende Dateien, die ich für die vollständige Umsetzung brauche.

[liest GetFileMetadataTool, LanguageService, sys_file_metadata-Struktur]

Schritt 1: AbstractFileTool erstellen
[erstellt Classes/MCP/Tool/File/AbstractFileTool.php mit resolveFile(), resolveLanguageUid(), buildLanguageSchemaProperty(), createJsonResult()]

Schritt 2: GetFileMetadataTool refaktorieren
[ändert extends AbstractTool → extends AbstractFileTool, entfernt duplizierte resolveFile() und resolveLanguageUid()]

Schritt 3: UploadFileTool erstellen
[erstellt Classes/MCP/Tool/File/UploadFileTool.php]

Schritt 4: SetFileMetadataTool erstellen
[erstellt Classes/MCP/Tool/File/SetFileMetadataTool.php]

Schritt 5: Tests erstellen
[erstellt UploadFileToolTest.php, SetFileMetadataToolTest.php]

Problem: 2 Test-Failures + Deprecation-Warnung
Failure: testUploadIntoSubfolder schlägt fehl. Diagnose: assertFalse($result→isError) schlägt fehl – Upload gibt Fehler zurück. Tatsächlicher Fehler: FAL-API.
Deprecation: DuplicationBehavior – alte String-Klasse vs. neue native Enum.

[analysiert ResourceStorage::addFile()-Signatur und DuplicationBehavior-Klassen]

Erkenntnis: TYPO3 13.4 hat zwei DuplicationBehavior-Klassen: alte String-Klasse (TYPO3\CMS\Core\Resource\DuplicationBehavior) und neue native Enum (TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior). Der instanceof-Check in addFile() prüft gegen die alte Klasse – daher Deprecation unvermeidbar bis TYPO3 v14.

[fixiert Test-Assertions mit besseren Fehlermeldungen, entfernt doppelte Helper-Methode]

Testergebnis nach Fix:
– GetFileMetadataTool: 6/6 ✓ (Refactoring-Verifikation)
– UploadFileTool: 11/11 ✓
– SetFileMetadataTool: 10/10 ✓
– Gesamte Test-Suite: 447/447 Tests bestanden

Deprecation-Warnung bleibt (TYPO3-internes Problem, nicht vermeidbar in v13).
Refactoring-Verifikation. Copilot führt die GetFileMetadataTool-Tests aus, bevor es neue Tests schreibt – um sicherzustellen, dass das Refactoring (AbstractFileTool) nichts kaputt gemacht hat. 6/6 grün = Refactoring sauber.
Deprecation korrekt eingeordnet. Copilot analysiert tief: zwei DuplicationBehavior-Klassen, instanceof-Check im TYPO3-Kern, Schlussfolgerung "unvermeidbar bis v14". Keine unnötigen Workarounds, klare Erklärung für den Entwickler.
Alle 447 Tests grün. Die gesamte bestehende Test-Suite wird nach der Implementierung durchgeführt. Keine Regression. Das ist echte Qualitätssicherung.
Terminal liefert teilweise keine Ausgabe. Wie in MCP3 und MCP4 – Copilot umgeht das Problem durch direktes Lesen der Dateien. Das Muster "Terminal-Tool instabil" zieht sich durch mehrere Sessions.
Austausch 3 — Bug-Report: UploadFile nicht gefunden
🐛

Produktionsproblem: Die KI kann das Tool nicht unter dem Namen "FileUpload" finden. Copilot muss diagnoszieren, ob das ein Naming-, Registrierungs- oder Cache-Problem ist.

Entwickler
die ai findet die FileUpload methode nicht in der TYPO3-MCP-API
Kurzer Bug-Report reicht. Nur eine Information: "findet nicht". Copilot muss selbst herausfinden, warum – Naming-Problem? Registrierungs-Problem? Cache-Problem? Die Diagnose ist Copilots Aufgabe.
"FileUpload" vs. "UploadFile". Die KI sucht nach "FileUpload", das Tool heißt aber "UploadFile". Das könnte schon die Ursache sein – oder ein Symptom davon, dass das Tool gar nicht sichtbar ist.
Copilot
Lass mich prüfen, wie die Tool-Registrierung und -Benennung funktioniert, und was der AI-Consumer tatsächlich sieht.

[liest AbstractTool→getName(): str_replace('Tool', '', 'UploadFileTool') = 'UploadFile']
Tool-Name ist "UploadFile", nicht "FileUpload". KI sucht also unter falschem Namen.

[prüft ob AbstractFileTool fälschlicherweise als Tool registriert wird]
AbstractFileTool ist abstract – Symfony DI instanziiert abstrakte Klassen nicht. ✓

[prüft Composer-Autoloading]
PSR-4-Konfiguration korrekt: Hn\McpServer\: resource: '../Classes/*' erfasst neuen File/-Namespace. ✓

Problem liegt woanders. Mögliche Ursachen:
1. DI-Container-Cache veraltet
2. ToolInterface-Tag wird nicht auf AbstractFileTool-Subklassen angewendet
3. Vererbungskette: UploadFileTool extends AbstractFileTool extends AbstractTool implements ToolInterface

Vererbungskette ist korrekt – AutoconfigureTag auf ToolInterface gilt für alle konkreten Unterklassen. ✓

[versucht MCP-Test-Command – Terminal hängt]
[flusht TYPO3 DI-Container-Cache]

Diagnose: Das Problem ist der TYPO3 DI-Container-Cache. Nach dem Hinzufügen neuer Klassen muss der Cache geleert werden, damit TYPO3 die neuen Services erkennt. Die Klassen selbst, das PSR-4-Autoloading und die AutoconfigureTag-Kette sind alle korrekt.
Systematische Diagnose. Copilot arbeitet die möglichen Ursachen systematisch ab: Naming ✓, AbstractFileTool-Registrierung ✓, PSR-4-Autoloading ✓, Vererbungskette ✓ – und landet schließlich beim DI-Cache als wahrscheinlichster Ursache.
Erster Hinweis: falscher Tool-Name. "FileUpload" vs. "UploadFile" – Copilot entdeckt sofort, dass die KI unter dem falschen Namen sucht. Das könnte allein schon die Erklärung sein. Cache-Flush macht den zweiten Schritt sicher.
Terminal hängt erneut. Auch der Versuch, mcp:test list auszuführen, schlägt fehl. Das Terminal-Problem ist konsistent über alle Sessions. In produktiven PhpStorm-Umgebungen sollte man dieses Problem durch ein IDE-Update oder Neustart lösen.
💡TYPO3 DI-Cache kennen. TYPO3 cached den Symfony DI-Container. Neue Klassen (auch mit AutoconfigureTag) sind erst sichtbar nach: php typo3 cache:flush --group=di oder über das TYPO3-Backend (Admin Tools → Maintenance). Copilot macht explizit darauf aufmerksam.

📦 Ergebnisse der Session

Neue Dateien

DateiBeschreibung
AbstractFileTool.phpAbstrakte Basisklasse: resolveFile(), resolveLanguageUid(), buildLanguageSchemaProperty(), createJsonResult()
UploadFileTool.phpbase64 → tempfile → $storage→addFile(); conflictMode; 10 MB Limit; Subfolder-Erstellung
SetFileMetadataTool.phpDataHandler update/localize; title, description, alternative, copyright, creator, categories; ISO-Sprachcodes
UploadFileToolTest.php11 Tests: Upload, Subfolder, createFolder, Konfliktmodi, Fehlerfälle, Schema
SetFileMetadataToolTest.php10 Tests: Default-Metadata, Multi-Field, lokalisiert, Fehlerfälle, Schema

Geänderte Dateien

DateiÄnderung
GetFileMetadataTool.phpRefactored: extends AbstractFileTool statt AbstractTool; duplizierte Methoden entfernt

Testergebnis

Test-SuiteErgebnis
GetFileMetadataTool (Refactoring-Verifikation)6/6 ✓
UploadFileTool11/11 ✓
SetFileMetadataTool10/10 ✓
Gesamte Test-Suite447/447 ✓

🎯 Fazit

🔬 Echtes Debugging in einer Produktions-Session

Session MCP5 ist die vollständigste des Projekts – Plan, Implementierung, Architektur-Upgrade, Deprecation-Diagnose, Refactoring-Verifikation, Gesamttest-Suite und abschließend DI-Cache-Debugging. Das ist eine reale Entwicklungs-Session, keine idealisiierte Demo.

Besonders lehrreich: Die DuplicationBehavior-Deprecation ist ein TYPO3-internes Problem, das nicht durch besseren Code gelöst werden kann. Copilot erkennt das, erklärt es klar und hört auf, nach Workarounds zu suchen. Das ist wichtige Selbsterkenntnis: Nicht jeder Fehler ist der eigene.

Der dritte Austausch zeigt, dass Copilot auch als Debugging-Partner funktioniert – systematische Hypothesen, schrittweise Elimination, klare Diagnose. Den DI-Cache-Flush hätte ein erfahrener TYPO3-Entwickler sofort vermutet; Copilot kommt nach mehreren Schritten zum selben Ergebnis.

🎓 Learnings

💡

7 Learnings aus Session MCP5

1

Refactoring als Teil der Implementierung planen

AbstractFileTool war nicht Teil des ursprünglichen Prompts – Copilot schlägt es vor, weil resolveFile() und resolveLanguageUid() in GetFileMetadataTool bereits existieren und kopiert werden würden. DRY-Refactoring ist leichter, wenn es im selben Zug wie eine Feature-Implementierung passiert.

2

Refactoring-Verifikation ist Pflicht

Nach dem Refactoring von GetFileMetadataTool auf AbstractFileTool führt Copilot die bestehenden Tests sofort durch – bevor neue Tests geschrieben werden. 6/6 grün = Refactoring sauber. Diesen Schritt nicht zu überspringen verhindert, dass Refactoring-Fehler in neuen Tests versteckt werden.

3

TYPO3 DI-Cache nach neuen Klassen flushen

Neue Klassen (auch mit AutoconfigureTag) sind erst nach Cache-Flush sichtbar. Symptom: Tool erscheint nicht in der Tool-Liste der KI. Lösung: php typo3 cache:flush --group=di. Das gilt für alle TYPO3 13+ Projekte mit Symfony DI.

4

Nicht jede Deprecation ist vermeidbar

Die DuplicationBehavior-Deprecation kommt aus dem TYPO3-Kern, nicht aus dem eigenen Code. Copilot analysiert die Ursache tief, stellt fest: "Erst in v14 gelöst" – und hört auf, Workarounds zu suchen. Copilot in Debugging-Sessions nicht zu drängen, "irgendetwas zu tun", wenn das Problem extern liegt.

5

Tool-Namen aus Klassennamen ableiten

TYPO3 MCP nutzt str_replace('Tool', '', ClassName): UploadFileToolUploadFile. Die KI sucht daher nach "UploadFile", nicht "FileUpload". Tool-Namen-Konventionen sind für die KI wichtig – falsche Namen führen zu "Tool nicht gefunden" ohne klare Fehlermeldung.

6

Gesamte Test-Suite nach Feature-Implementierung ausführen

Copilot führt nach der Implementierung alle 447 Tests aus, nicht nur die neuen 21 Tests. Das ist der einzige zuverlässige Weg, Regressionen zu finden. Wenn das in Ihrer PhpStorm-Konfiguration nicht automatisch passiert, fordert man Copilot explizit auf: "run the full test suite".

7

DataHandler localize vs. update – der Unterschied

Bei SetFileMetadata muss Copilot unterscheiden: Gibt es bereits eine Übersetzung in der Zielsprache? Ja → DataHandler update. Nein → DataHandler localize-Command, der die Übersetzung anlegt und dann die Felder setzt. Dieser Unterschied ist TYPO3-spezifisch und wurde korrekt im Plan erfasst.

📊 Session-Qualität im Überblick

ElementQualitätAnmerkung
Austausch 1 – Prompt✓ Sehr gut"AI generated images" konkretisiert den Use-Case; "set and translate metadata" fordert Lokalisierung
Austausch 1 – Antwort✓ ExzellentAbstractFileTool eigenständig vorgeschlagen, DataHandler localize korrekt, Zweiformat-API, 10 MB Limit
Austausch 2 – Prompt✓ Gut"Start implementation" – minimaler Trigger
Austausch 2 – Antwort✓ ExzellentRefactoring-Verifikation, Deprecation korrekt eingeordnet, 447/447 Tests grün, vollständige Zusammenfassung
Austausch 3 – Prompt✓ GutKurzer Bug-Report ohne überflüssige Infos
Austausch 3 – Antwort✓ Sehr gutSystematische Diagnose, falscher Tool-Name erkannt, DI-Cache als Ursache identifiziert

🔗 Weitere Walk-Throughs